<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://blog.parisni.com/atom.xml</id>
  <title>Software Lobotomy &amp;mdash; blog</title>
  <updated>2026-04-11T14:26:41.882452+00:00</updated>
  <author>
    <name>Nicolas Paris</name>
    <email>parisni@riseup.net</email>
  </author>
  <generator uri="https://lkiesow.github.io/python-feedgen" version="0.9.0">python-feedgen</generator>
  <logo>https://blog.parisni.com/images/favicon.webp</logo>
  <subtitle>parisni's blog</subtitle>
  <entry>
    <id>https://blog.parisni.com/blog/concourse</id>
    <title>Concourse</title>
    <updated>2023-09-11T14:42:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;h1&gt;Concourse&lt;/h1&gt;
&lt;h2&gt;Commands&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;&lt;span class="hl slc"&gt;# create/update a pipeline&lt;/span&gt;
fly &lt;span class="hl kwb"&gt;-t&lt;/span&gt; tutorial &lt;span class="hl kwb"&gt;set-pipeline -c&lt;/span&gt; pipeline.yml &lt;span class="hl kwb"&gt;-p&lt;/span&gt; hello&lt;span class="hl kwb"&gt;-world&lt;/span&gt; 

&lt;span class="hl slc"&gt;# trigger a job&lt;/span&gt;
fly &lt;span class="hl kwb"&gt;-t&lt;/span&gt; tutorial trigger&lt;span class="hl kwb"&gt;-job -j&lt;/span&gt;  hello&lt;span class="hl kwb"&gt;-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;job&lt;span class="hl kwb"&gt;-hello-world&lt;/span&gt;

&lt;span class="hl slc"&gt;# ask for pipeline builds&lt;/span&gt;
fly &lt;span class="hl kwb"&gt;-t&lt;/span&gt; tutorial builds
id  name                           status     start                     end                       duration  team  created by
&lt;span class="hl num"&gt;60&lt;/span&gt;  hello&lt;span class="hl kwb"&gt;-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;job&lt;span class="hl kwb"&gt;-hello-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;&lt;span class="hl num"&gt;4&lt;/span&gt;  succeeded  &lt;span class="hl num"&gt;2023&lt;/span&gt;&lt;span class="hl kwb"&gt;-08-28&lt;/span&gt;@&lt;span class="hl num"&gt;16&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;34&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;11&lt;/span&gt;&lt;span class="hl opt"&gt;+&lt;/span&gt;&lt;span class="hl num"&gt;0200  2023&lt;/span&gt;&lt;span class="hl kwb"&gt;-08-28&lt;/span&gt;@&lt;span class="hl num"&gt;16&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;34&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;14&lt;/span&gt;&lt;span class="hl opt"&gt;+&lt;/span&gt;&lt;span class="hl num"&gt;0200  3&lt;/span&gt;s        main  admin
&lt;span class="hl num"&gt;59&lt;/span&gt;  hello&lt;span class="hl kwb"&gt;-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;job&lt;span class="hl kwb"&gt;-hello-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt;  succeeded  &lt;span class="hl num"&gt;2023&lt;/span&gt;&lt;span class="hl kwb"&gt;-08-28&lt;/span&gt;@&lt;span class="hl num"&gt;16&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;26&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;01&lt;/span&gt;&lt;span class="hl opt"&gt;+&lt;/span&gt;&lt;span class="hl num"&gt;0200  2023&lt;/span&gt;&lt;span class="hl kwb"&gt;-08-28&lt;/span&gt;@&lt;span class="hl num"&gt;16&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;26&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;04&lt;/span&gt;&lt;span class="hl opt"&gt;+&lt;/span&gt;&lt;span class="hl num"&gt;0200  3&lt;/span&gt;s        main  admin
&lt;span class="hl num"&gt;15&lt;/span&gt;  hello&lt;span class="hl kwb"&gt;-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;job&lt;span class="hl kwb"&gt;-hello-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;&lt;span class="hl num"&gt;2&lt;/span&gt;  failed     &lt;span class="hl num"&gt;2023&lt;/span&gt;&lt;span class="hl kwb"&gt;-08-28&lt;/span&gt;@&lt;span class="hl num"&gt;15&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;34&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;40&lt;/span&gt;&lt;span class="hl opt"&gt;+&lt;/span&gt;&lt;span class="hl num"&gt;0200  2023&lt;/span&gt;&lt;span class="hl kwb"&gt;-08-28&lt;/span&gt;@&lt;span class="hl num"&gt;15&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;34&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;43&lt;/span&gt;&lt;span class="hl opt"&gt;+&lt;/span&gt;&lt;span class="hl num"&gt;0200  3&lt;/span&gt;s        main  admin
&lt;span class="hl num"&gt;13&lt;/span&gt;  hello&lt;span class="hl kwb"&gt;-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;job&lt;span class="hl kwb"&gt;-hello-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;&lt;span class="hl num"&gt;1&lt;/span&gt;  succeeded  &lt;span class="hl num"&gt;2023&lt;/span&gt;&lt;span class="hl kwb"&gt;-08-28&lt;/span&gt;@&lt;span class="hl num"&gt;14&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;50&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;49&lt;/span&gt;&lt;span class="hl opt"&gt;+&lt;/span&gt;&lt;span class="hl num"&gt;0200  2023&lt;/span&gt;&lt;span class="hl kwb"&gt;-08-28&lt;/span&gt;@&lt;span class="hl num"&gt;14&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;50&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;52&lt;/span&gt;&lt;span class="hl opt"&gt;+&lt;/span&gt;&lt;span class="hl num"&gt;0200  3&lt;/span&gt;s        main  admin

&lt;span class="hl slc"&gt;# watch a pipeline / job / build-number&lt;/span&gt;
fly &lt;span class="hl kwb"&gt;-t&lt;/span&gt; tutorial watch &lt;span class="hl kwb"&gt;-j&lt;/span&gt; hello&lt;span class="hl kwb"&gt;-world&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;job&lt;span class="hl kwb"&gt;-hello-world --build&lt;/span&gt; &lt;span class="hl num"&gt;4&lt;/span&gt;

&lt;span class="hl slc"&gt;# destroy pipelines&lt;/span&gt;
fly &lt;span class="hl kwb"&gt;-t&lt;/span&gt; tutorial destroy&lt;span class="hl kwb"&gt;-pipeline -p&lt;/span&gt; hello&lt;span class="hl kwb"&gt;-world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Parameter&amp;gt; Values in params sections in turn become environment variables within the task:&lt;/h2&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Concourse — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2023-09-11 14:42&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/concourse" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/hive-reflexion</id>
    <title>Hive Reflexions</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;p&gt;&lt;span&gt;Date:&lt;time id="post-date"&gt;2018-05-10&lt;/time&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="hive-reflexions"&gt;Hive Reflexions&lt;/h1&gt;
&lt;p&gt;Hive has several advantages over other Datawarehouse solutions.&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;it is java based. This allows it to take advantage of UDF. The best
and the moste complicate way to write them as generic UDFs. The other
important aspect is to make them &lt;span class="title-ref"&gt;blessed
UDF&lt;/span&gt; by mean they are global and accessible to any user. Generic
UDF can produce any hive type from integer to complexe map
structure.&lt;/li&gt;
&lt;li&gt;it can read/write into hbase and take advantage of a key-value
store.&lt;/li&gt;
&lt;li&gt;it is ACID compliant, and provide both insert/update. However, this
new feature is not well integrated with other tools such apache spark or
facebook presto.&lt;/li&gt;
&lt;li&gt;it supports multiple level of performance tunning such
partitionning, bucketting, bloom filters, predicate pushdown.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Still hive has several disavantages:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;lack or support for sequences. The workaround right now is to either
use a UUID - this has several drawbacks such performances/storage issue.
A second approach is to use the &lt;span class="title-ref"&gt;sequence_nb +
(row_number() over())&lt;/span&gt; function where &lt;span class="title-ref"&gt;sequence_nb&lt;/span&gt; is maintained into a table - the
count of the inserted rows need to be added to the sequence. The last
solution is a long, but it cannot be used concurrently. The solution
cannot be used in production.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="hive-configuration-tips"&gt;hive configuration tips&lt;/h1&gt;
&lt;p&gt;Hive can have OOM. Then this parameter might help - &lt;span class="title-ref"&gt;set hive.exec.orc.memory.pool = 1.0&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Predicate Push Down is better when INSERT STMT use a SORT BY
"orc.bloom.filter.columns"="col1,col2"&lt;/p&gt;
&lt;p&gt;It is also possible to update the bloom filter by running: &lt;span class="title-ref"&gt;ANALYZE TABLE Table1 COMPUTE STATISTICS FOR
COLUMNS;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@anishekagarwal/apache-hive-beeline-progress-bar-fd57c29da65d"&gt;show
progress bar in beeline&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Hive Reflexions — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/hive-reflexion" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/postgresql-reflexion</id>
    <title>PostgreSQL Reflexions</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-05-13&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="postgresql-reflexions"&gt;PostgreSQL Reflexions&lt;/h1&gt;
&lt;p&gt;After 4 years of postgresql management, I d'like to relate my
experience.&lt;/p&gt;
&lt;p&gt;Postgreql is incredible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;its community is wonderful, the mailing list is very active and
structured&lt;/li&gt;
&lt;li&gt;the recent years have been very productive for postgres, with many
analytics improvements and perspectives&lt;/li&gt;
&lt;li&gt;it has one of the best support for transactions, and for example
deal with DDL in transaction&lt;/li&gt;
&lt;li&gt;it's stable, we never had any crash in 4 years, or need to reboot
the server&lt;/li&gt;
&lt;li&gt;it manage bot structured and unstructured data&lt;/li&gt;
&lt;li&gt;free text indexes and features are very advanced&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, sadly postgresql has some drawnbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it does not deal great with large volumne when comes analytics&lt;/li&gt;
&lt;li&gt;because it may be used for all batch ingesting, batch exporting,
OLTP, dumps, analytics, the overall performances might be affected&lt;/li&gt;
&lt;li&gt;it does not scale horizontaly&lt;/li&gt;
&lt;li&gt;it has no fail over, or this lead to complex setup&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Complementing postgresql with hadoop:&lt;/p&gt;
&lt;p&gt;For this reason, it has been decided to externalize some
responsibilities such batch exporting and analytics to an other
technology that scale horizontally: hadoop.&lt;/p&gt;
&lt;p&gt;The good point is synchronizing data from postgresql to hive daily is
easy thanks to incremental sqoop import on hdfs, based on indexed
timestamps in postgreql. This allows pushing the data from postgresql to
hive ready to analyse. The two tools interface well where hive does not
handle sequence, or triggers, and postgresql does not manage huge data
historisation, and columnar aggregation.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;While postgreqsl does not handle well aggregations on bilions rows,
it's children greenplum is supposed to.&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Let's envisage a greenplum post soon.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=PostgreSQL Reflexions — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/postgresql-reflexion" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/hive-merge</id>
    <title>Hive Merge</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-05-13&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;2 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="hive-merge"&gt;Hive Merge&lt;/h1&gt;
&lt;p&gt;Hive introduced ACID statement: INSERT, UPDATE, DELETE &amp;amp; MERGE.
It turns-out HIVE 1.2.x is not optimised enough to support MERGE
efficiently. An in depth documentation can be found &lt;a href="https://cwiki.apache.org/confluence/display/Hive/Hive+Transactions#HiveTransactions-Limitations"&gt;there&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The code below :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is idempotent in someway. Suppose for some reason, the &lt;span class="title-ref"&gt;merge insert&lt;/span&gt; statement fails. Then running
again all statements won't be an issue since no update at all will
append again. Same case if the &lt;span class="title-ref"&gt;update&lt;/span&gt;
statement fails.&lt;/li&gt;
&lt;li&gt;Simple version: makes the assumption that any data both present in
the &lt;span class="title-ref"&gt;staging&lt;/span&gt; table and the &lt;span class="title-ref"&gt;target&lt;/span&gt; table needs to be updated.&lt;/li&gt;
&lt;li&gt;SCD1 and SCD2 have slighly difference that are mentionned if
existing.&lt;/li&gt;
&lt;li&gt;SCD2 has been tested (upsert version) on a large target table ( 1.3
Bilion rows * 100 columns) and a source table of 100 Milion rows. As a
result, the total runtime was les than 3 hours. (50% resource on a 5
computer hadoop cluster).&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="staging-step"&gt;0) Staging step&lt;/h1&gt;
&lt;p&gt;Some data was put on hdfs in the &amp;lt;stg_table&amp;gt; to be merged with
a target table. This might be done by scoop incrementally. Also, this
might be the whole table. All the steps below will work the same in both
case.&lt;/p&gt;
&lt;h1 id="preparation-step"&gt;1) Preparation step&lt;/h1&gt;
&lt;p&gt;The 3 table above are necessary for any of SCD1 or SCD2. They are
respectively the &lt;span class="title-ref"&gt;transformation&lt;/span&gt;, &lt;span class="title-ref"&gt;insert&lt;/span&gt;, &lt;span class="title-ref"&gt;update&lt;/span&gt;
candidate tables.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- create transformation table&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;CREATE&lt;/span&gt; &lt;span class="kw"&gt;TEMPORARY&lt;/span&gt; &lt;span class="kw"&gt;TABLE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;trf_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;LIKE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- create insert table&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;CREATE&lt;/span&gt; &lt;span class="kw"&gt;TEMPORARY&lt;/span&gt; &lt;span class="kw"&gt;TABLE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;ins_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;LIKE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a href="#cb1-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb1-7"&gt;&lt;a href="#cb1-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- create update table&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-8"&gt;&lt;a href="#cb1-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;CREATE&lt;/span&gt; &lt;span class="kw"&gt;TEMPORARY&lt;/span&gt; &lt;span class="kw"&gt;TABLE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;LIKE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="transformation-step"&gt;2) Transformation step&lt;/h1&gt;
&lt;p&gt;This step loads the trf table (&lt;span class="title-ref"&gt;transformed&lt;/span&gt;) from the stg table (&lt;span class="title-ref"&gt;staging&lt;/span&gt;). It adds the hash column, and is the
place to add other transformations/columns if needed.&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- example without transformations&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;trf_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; , &lt;span class="kw"&gt;HASH&lt;/span&gt;(&lt;span class="op"&gt;*&lt;/span&gt;) &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="kw"&gt;hash&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;stg_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;;&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- example with transformations&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- t1 and t2 are new columns added&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-8"&gt;&lt;a href="#cb2-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;trf_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-9"&gt;&lt;a href="#cb2-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; , &lt;span class="kw"&gt;HASH&lt;/span&gt;(stg.&lt;span class="op"&gt;*&lt;/span&gt;) &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="kw"&gt;hash&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-10"&gt;&lt;a href="#cb2-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; , t1(), t2()&lt;/span&gt;
&lt;span id="cb2-11"&gt;&lt;a href="#cb2-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;stg_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;) &lt;span class="kw"&gt;as&lt;/span&gt; stg;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="dispatching-step"&gt;3) Dispatching step&lt;/h1&gt;
&lt;p&gt;Simplified version:&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- variation when you already know that rows are all different&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;trf_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;maj_date&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;IS&lt;/span&gt; &lt;span class="kw"&gt;NOT&lt;/span&gt; &lt;span class="kw"&gt;NULL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;ins_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;maj_date&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;IS&lt;/span&gt; &lt;span class="kw"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Complete version:&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- feed both update &amp;amp; insert table&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;FROM&lt;/span&gt;  &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;trf_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; trf&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;JOIN&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; targ&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;ON&lt;/span&gt; (&lt;/span&gt;
&lt;span id="cb4-6"&gt;&lt;a href="#cb4-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      targ.&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;end_date&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;IS&lt;/span&gt; &lt;span class="kw"&gt;NULL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-7"&gt;&lt;a href="#cb4-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;AND&lt;/span&gt; trf.&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; targ.&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-8"&gt;&lt;a href="#cb4-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      )&lt;/span&gt;
&lt;span id="cb4-9"&gt;&lt;a href="#cb4-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-10"&gt;&lt;a href="#cb4-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;AND&lt;/span&gt; trf.&lt;span class="kw"&gt;hash&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; targ.&lt;span class="kw"&gt;hash&lt;/span&gt;) &lt;span class="kw"&gt;as&lt;/span&gt; updateable&lt;/span&gt;
&lt;span id="cb4-11"&gt;&lt;a href="#cb4-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="kw"&gt;TABLE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; ;&lt;/span&gt;
&lt;span id="cb4-12"&gt;&lt;a href="#cb4-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-13"&gt;&lt;a href="#cb4-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- feed the insert table with new rows&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-14"&gt;&lt;a href="#cb4-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;ins_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-15"&gt;&lt;a href="#cb4-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-16"&gt;&lt;a href="#cb4-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;trf_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-17"&gt;&lt;a href="#cb4-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-18"&gt;&lt;a href="#cb4-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;AND&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;NOT&lt;/span&gt; &lt;span class="kw"&gt;IN&lt;/span&gt; (&lt;/span&gt;
&lt;span id="cb4-19"&gt;&lt;a href="#cb4-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-20"&gt;&lt;a href="#cb4-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-21"&gt;&lt;a href="#cb4-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="upsert-version"&gt;4.1) Upsert version&lt;/h1&gt;
&lt;p&gt;SCD 1:&lt;/p&gt;
&lt;p&gt;Notice the delete is used in place of an update. The reason is an
update cannot join an other table and thus apply updates where
needed.&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb5-1"&gt;&lt;a href="#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- first delete update rows&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;DELETE&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;AND&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;IN&lt;/span&gt; (&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-6"&gt;&lt;a href="#cb5-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;);&lt;/span&gt;
&lt;span id="cb5-7"&gt;&lt;a href="#cb5-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-8"&gt;&lt;a href="#cb5-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- second, insert all new rows&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-9"&gt;&lt;a href="#cb5-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-10"&gt;&lt;a href="#cb5-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-11"&gt;&lt;a href="#cb5-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;ins_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-12"&gt;&lt;a href="#cb5-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-13"&gt;&lt;a href="#cb5-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-14"&gt;&lt;a href="#cb5-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;SCD 2:&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb6-1"&gt;&lt;a href="#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- first update old rows&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;UPDATE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SET&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;end_date&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;current_date&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;AND&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;end_date&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;IS&lt;/span&gt; &lt;span class="kw"&gt;NULL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-6"&gt;&lt;a href="#cb6-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;AND&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;IN&lt;/span&gt; (&lt;/span&gt;
&lt;span id="cb6-7"&gt;&lt;a href="#cb6-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-8"&gt;&lt;a href="#cb6-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;);&lt;/span&gt;
&lt;span id="cb6-9"&gt;&lt;a href="#cb6-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-10"&gt;&lt;a href="#cb6-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- second, insert all new rows&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-11"&gt;&lt;a href="#cb6-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-12"&gt;&lt;a href="#cb6-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-13"&gt;&lt;a href="#cb6-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;ins_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-14"&gt;&lt;a href="#cb6-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-15"&gt;&lt;a href="#cb6-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-16"&gt;&lt;a href="#cb6-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="merge-version"&gt;4.2) Merge version&lt;/h1&gt;
&lt;p&gt;SCD 1:&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb7-1"&gt;&lt;a href="#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- first update old rows&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;MERGE&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;USING&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-4"&gt;&lt;a href="#cb7-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;/span&gt;
&lt;span id="cb7-5"&gt;&lt;a href="#cb7-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="kw"&gt;null&lt;/span&gt; &lt;span class="kw"&gt;AS&lt;/span&gt; join_key, upd.&lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-6"&gt;&lt;a href="#cb7-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-7"&gt;&lt;a href="#cb7-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;AS&lt;/span&gt; join_key, ins.&lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;ins_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-8"&gt;&lt;a href="#cb7-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;) &lt;span class="kw"&gt;AS&lt;/span&gt; sub&lt;/span&gt;
&lt;span id="cb7-9"&gt;&lt;a href="#cb7-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;ON&lt;/span&gt; (sub.join_key &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;.join_key&lt;/span&gt;
&lt;span id="cb7-10"&gt;&lt;a href="#cb7-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;.&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;end_date&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;IS&lt;/span&gt; &lt;span class="kw"&gt;NULL&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb7-11"&gt;&lt;a href="#cb7-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;WHEN&lt;/span&gt; MATCHED&lt;/span&gt;
&lt;span id="cb7-12"&gt;&lt;a href="#cb7-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="cf"&gt;THEN&lt;/span&gt; &lt;span class="kw"&gt;UPDATE&lt;/span&gt; &lt;span class="kw"&gt;SET&lt;/span&gt; col1&lt;span class="op"&gt;=&lt;/span&gt;sub.col1, &lt;span class="op"&gt;..&lt;/span&gt;. , &lt;span class="kw"&gt;hash&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;sub.&lt;span class="kw"&gt;hash&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-13"&gt;&lt;a href="#cb7-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;WHEN&lt;/span&gt; &lt;span class="kw"&gt;NOT&lt;/span&gt; MATCHED&lt;/span&gt;
&lt;span id="cb7-14"&gt;&lt;a href="#cb7-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="cf"&gt;THEN&lt;/span&gt; &lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;VALUES&lt;/span&gt; (sub.col1, &lt;span class="op"&gt;..&lt;/span&gt;. , sub.&lt;span class="kw"&gt;hash&lt;/span&gt;) ;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;SCD 2:&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb8-1"&gt;&lt;a href="#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- first update old rows&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;MERGE&lt;/span&gt; &lt;span class="kw"&gt;INTO&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;USING&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="kw"&gt;null&lt;/span&gt; &lt;span class="kw"&gt;AS&lt;/span&gt; join_key, upd.&lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-6"&gt;&lt;a href="#cb8-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-7"&gt;&lt;a href="#cb8-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="kw"&gt;null&lt;/span&gt; &lt;span class="kw"&gt;AS&lt;/span&gt; join_key, ins.&lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;ins_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-8"&gt;&lt;a href="#cb8-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-9"&gt;&lt;a href="#cb8-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;primary_key&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;AS&lt;/span&gt; join_key, ins.&lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;upd_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-10"&gt;&lt;a href="#cb8-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;) &lt;span class="kw"&gt;AS&lt;/span&gt; sub&lt;/span&gt;
&lt;span id="cb8-11"&gt;&lt;a href="#cb8-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;ON&lt;/span&gt; (sub.join_key &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;.join_key&lt;/span&gt;
&lt;span id="cb8-12"&gt;&lt;a href="#cb8-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;target_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;.&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;end_date&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;IS&lt;/span&gt; &lt;span class="kw"&gt;NULL&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-13"&gt;&lt;a href="#cb8-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;WHEN&lt;/span&gt; MATCHED&lt;/span&gt;
&lt;span id="cb8-14"&gt;&lt;a href="#cb8-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="cf"&gt;THEN&lt;/span&gt; &lt;span class="kw"&gt;UPDATE&lt;/span&gt; &lt;span class="kw"&gt;SET&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;end_date&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;current_date&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb8-15"&gt;&lt;a href="#cb8-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;WHEN&lt;/span&gt; &lt;span class="kw"&gt;NOT&lt;/span&gt; MATCHED&lt;/span&gt;
&lt;span id="cb8-16"&gt;&lt;a href="#cb8-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="cf"&gt;THEN&lt;/span&gt; &lt;span class="kw"&gt;INSERT&lt;/span&gt; &lt;span class="kw"&gt;VALUES&lt;/span&gt; (sub.col1, &lt;span class="op"&gt;..&lt;/span&gt;. , sub.&lt;span class="kw"&gt;hash&lt;/span&gt;) ;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Hive Merge — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/hive-merge" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/spark-reflexion</id>
    <title>Spark Reflexions</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-05-13&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="spark-reflexions"&gt;Spark Reflexions&lt;/h1&gt;
&lt;p&gt;Spark is a Swiss Army Knife of a hadoop stack. It makes glue between
tools and is a de-facto interface for them.&lt;/p&gt;
&lt;p&gt;Spark has a lot of advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it's a wonderfull connector: if you look at a way to connect to a
tool, spark already has a connector for you. Special mention to csv:
spark is also able to read multilined csv with quote, empty lines and
special character in it.&lt;/li&gt;
&lt;li&gt;it can manipulate very huge dataset: in case the dataset does not
feat in memory, the spark partitionning feature allows spliting the
tasks in working pipelines&lt;/li&gt;
&lt;li&gt;its parallel feature can take advantage of a hadoop cluster, but is
a great solution for a laptop too&lt;/li&gt;
&lt;li&gt;the scala spark-shell is really handy for development. It's
auto-completion features are superior to any shell I've dealt with
before&lt;/li&gt;
&lt;li&gt;it has SQL syntax, SPARKQL compliance, and also machine learning
distributed implementation.&lt;/li&gt;
&lt;li&gt;it can be programmed in scala, python, R, java and julia.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Spark as some disadvantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;time of writing, spark does not support hive ACID tables. The
workaround is to do a major compaction of the table before reading it
with spark. This means it cannot yet be integrated into a hive ETL
process based on ACID tables.&lt;/li&gt;
&lt;li&gt;spark programming needs a lot of skills. It is then not a good
choice for intermediate enterprise in comparison to hive programming.
Again, hive ETL looks a better fit for a maintainability reason.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Spark Reflexions — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/spark-reflexion" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/hbase-reflexion</id>
    <title>Hbase Reflexions</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-05-13&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="hbase-reflexions"&gt;Hbase Reflexions&lt;/h1&gt;
&lt;p&gt;hbase looks a powerfull tool in complement of hive. While hive suits
well for ETL and data historisation, it cannot offer sub-second access
to thousand of concurrent users.&lt;/p&gt;
&lt;p&gt;Hbase comes with a powerful compagnion aka Phoenix that provides many
features, while keeping the hbase features intact. Phoenix provides a
jdbc driver to hbase. This distinction adds many improvements:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;it offers sql, joins, secondary indexes, transactions, sequences on
top of hbase.&lt;/li&gt;
&lt;li&gt;it simplifies hive, spark, solr, and general programming access to
hbase data.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="jdbc-overview"&gt;JDBC overview&lt;/h2&gt;
&lt;p&gt;jdbc access can be done with &lt;a href="https://community.hortonworks.com/questions/47138/phoenix-query-server-connection-url-example.html"&gt;kerberos&lt;/a&gt;
on the form&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;"jdbc:phoenix:thin:url=&amp;lt;scheme&amp;gt;://&amp;lt;server-hostname&amp;gt;:&amp;lt;port&amp;gt;;authentication=SPNEGO;principal=my_user;keytab=/home/my_user/my_user.keytab"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Phoenix connection thought JDBC needs : - a jdbc jar file - the
hbase-site.conf - a kerberos ticket&lt;/p&gt;
&lt;p&gt;Phoenix does not provide a way for connection pooling. The costly
part of the connection is the hbase link. However it is cached within
the region servers and a new phoenix jdbc connection can be rebuild for
every query since it is a lightweight object.&lt;/p&gt;
&lt;h2 id="hive-integration"&gt;Hive integration&lt;/h2&gt;
&lt;p&gt;Phoenix tables can be mounted into hive thanks to a &lt;a href="https://phoenix.apache.org/hive_storage_handler.html"&gt;recent
plugin&lt;/a&gt;. In comparaison to hbase plugin, this allows fast join to
hive table (to be tested). While this plugin needs phoenix 4.8.0+ HDP
ships with phoenix 4.7.0. However HDP Phoenix is a fork of Phoenix, and
it integrates this feature.&lt;/p&gt;
&lt;p&gt;Because phoenix allows to mount a hbase table, hive a phoenix or a
hbase table, there is many ways to make hive querying hbase. Moreover
hive can create a regular table stored as a hbase or phoenix table wich
is slightly different. The best way is to mount phoenix as a hive
external table. First advantage is &lt;em&gt;phoenix&lt;/em&gt; allows salted tables
by mean there is no need to manually handle the key to be well
distributed. Second, is loading directly into &lt;em&gt;phoenix&lt;/em&gt; allows it
to manage its secondary indexes and also some other tools such
&lt;em&gt;solr&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Finally, hive can access an external &lt;em&gt;phoenix&lt;/em&gt; table and allow
both upsert and select. The plugin also provides a way to delete/update
from hive, however I haven't been able to reproduce yet since
transactional tables are only compatible with orc based tables.&lt;/p&gt;
&lt;h2 id="spark-integration"&gt;Spark integration&lt;/h2&gt;
&lt;p&gt;Spark can read and write from phoenix &lt;a href="https://stackoverflow.com/questions/40329968/apache-spark-ways-to-read-and-write-from-apache-phoenix-in-java"&gt;here
on SOF&lt;/a&gt; or &lt;a href="https://phoenix.apache.org/phoenix_spark.html"&gt;here on
official&lt;/a&gt;. The good point is it can be done from scala or python.&lt;/p&gt;
&lt;h2 id="solr-integration"&gt;Solr integration&lt;/h2&gt;
&lt;p&gt;Solr integration with hbase is a good idea: hbase contains the truth
and solr allows fast lookup to discover it. However, setting up solr on
top of hbase is a pain. Phoenix simplifies drastically that : &lt;a href="https://nicholasmaillard.wordpress.com/2014/12/27/phoenix-to-solr-in-20-minutes/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Hbase Reflexions — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/hbase-reflexion" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/prestodb-reflexion</id>
    <title>PrestoDB reflexions</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-05-13&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="prestodb-reflexions"&gt;PrestoDB reflexions&lt;/h1&gt;
&lt;p&gt;Prestodb is a cool distributed engine over hadoop. It can be compared
to hive LLAP, impala or apache DRILL for fast in-memory OLAP analysis
and data discovery.&lt;/p&gt;
&lt;p&gt;The main disadvantages it has right now are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it is not ACID compliant and far from being: this means tables in
presto shall be created from scratch for analytics. Because we are
speaking about big data, this implies copying&lt;/li&gt;
&lt;li&gt;it does not and never will support hive views: this would have been
an opportunity to create pseudo-acid workflows&lt;/li&gt;
&lt;li&gt;it does not integrate with hbase&lt;/li&gt;
&lt;li&gt;it does not integrate with YARN, or at least the attempt looks
discontinued on github.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main advantage it has over hive LLAP are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;many more build-in functions&lt;/li&gt;
&lt;li&gt;has been proven to scale well with tons of users&lt;/li&gt;
&lt;li&gt;integrates with RDBMS such postgres or NOSQL stores such
mongodb&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sor far, the best feet for our internal arhitecture is to go with
hive llap in replacement to prestodb. This will brings us the ability to
better integrate with hbase/phoenix/solr from one part, and also give us
the ability to query ACID version of the DWH without data
deduplication.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=PrestoDB reflexions — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/prestodb-reflexion" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/yarn-reflexion</id>
    <title>Yarn Reflexions</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-05-16&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="yarn-reflexions"&gt;Yarn Reflexions&lt;/h1&gt;
&lt;p&gt;Here are some Apache Yarn consideratoins.&lt;/p&gt;
&lt;h2 id="yarn-is-so-great"&gt;Yarn is so great&lt;/h2&gt;
&lt;dl&gt;
&lt;dt&gt;Queue modifications&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Some application needs extra cores/memory and need to be boosted
somehow? Yarns allows on the fly adjustement of queues. In our case, we
have nightly ETL and online users the day. It's then easy to dispatch
the resources where needed, and without turning off running
application.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;GPU management&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Hadoop 3 will provide a new dimension in yarn responsibility. Yarn
will be able to allocate GPU resources for users. This will be of
incredible help for machine learning programs and users to share and
optimize access to them.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2 id="yarn-has-some-drawbacks"&gt;Yarn has some drawbacks&lt;/h2&gt;
&lt;dl&gt;
&lt;dt&gt;Applications logs&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;They are stored locally. Same case for temporary files on the local
filesystem such map results. And there is no trivial way to store point
to hdfs. This is an essential point when configuring the cluster,
because the disk allocated for storing yarn user files (hive, spark....)
is a real bottleneck. Depending on the cluster workload, keep in mind
having a minimum of 2TO for this stuff, per machine.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Yarn superuser&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;There is now way to kill a process if you are not the owner of the
process. This makes things a bit more complex for an admin to supervise
such platform.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Yarn Reflexions — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/yarn-reflexion" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/termite</id>
    <title>Best terminal Emulator</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-05-27&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="best-terminal-emulator"&gt;Best terminal Emulator&lt;/h1&gt;
&lt;p&gt;Termite is way better than my previous terminals. It's sensibly based
on vim paradigm. It's able to look ahead in the history, copy from it
and back to insert mode.&lt;/p&gt;
&lt;p&gt;An other great aspect is it notifies when something happens in it,
such end of process, new mail an so on.&lt;/p&gt;
&lt;h2 id="keybinding"&gt;keybinding&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;ctrl+space&lt;/em&gt; : insert mode&lt;/li&gt;
&lt;li&gt;&lt;em&gt;escape&lt;/em&gt; : normal mode&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Best terminal Emulator — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/termite" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/jupyter-notenbooks-and-conda</id>
    <title>Jupyter Notebooks and Conda</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-06-02&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="jupyter-notebooks-and-conda"&gt;Jupyter Notebooks and Conda&lt;/h1&gt;
&lt;p&gt;After creating a environment with conda and installing packages, the
jupyter notebook environment may not see them. The method below adds a
new kernel based on the later environment and allow to benefit from
conda:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;conda&lt;/span&gt; activate my-env&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;conda&lt;/span&gt;  create &lt;span class="at"&gt;-n&lt;/span&gt; my-env pip setuptools ipykernel python=3.5&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;python&lt;/span&gt; &lt;span class="at"&gt;-m&lt;/span&gt; ipykernel install &lt;span class="at"&gt;--user&lt;/span&gt; &lt;span class="at"&gt;--name&lt;/span&gt; my-env &lt;span class="at"&gt;--display-name&lt;/span&gt; &lt;span class="st"&gt;"Python (my-env)"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Jupyter Notebooks and Conda — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/jupyter-notenbooks-and-conda" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/maven-local</id>
    <title>Managing local jars with
maven</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-06-02&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="managing-local-jars-with-maven"&gt;Managing local jars with
maven&lt;/h1&gt;
&lt;p&gt;Maven has for me a non user friendly documentation, with 80% of xml
content. For long time I have been stuck in how easily manage both
dependency from maven central and from local jars.&lt;/p&gt;
&lt;p&gt;I finally got something quite general and functional. Here is how to
make this working fine:&lt;/p&gt;
&lt;p&gt;The pom.xml file:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode xml"&gt;&lt;code class="sourceCode xml"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;&amp;lt;!-- Add the manifest --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&amp;lt;&lt;span class="kw"&gt;plugin&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;groupId&lt;/span&gt;&amp;gt;org.apache.maven.plugins&amp;lt;/&lt;span class="kw"&gt;groupId&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;artifactId&lt;/span&gt;&amp;gt;maven-jar-plugin&amp;lt;/&lt;span class="kw"&gt;artifactId&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;version&lt;/span&gt;&amp;gt;2.4&amp;lt;/&lt;span class="kw"&gt;version&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a href="#cb1-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;configuration&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-7"&gt;&lt;a href="#cb1-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &amp;lt;&lt;span class="kw"&gt;archive&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-8"&gt;&lt;a href="#cb1-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &amp;lt;&lt;span class="kw"&gt;manifest&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-9"&gt;&lt;a href="#cb1-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &amp;lt;&lt;span class="kw"&gt;mainClass&lt;/span&gt;&amp;gt;your.class.Main&amp;lt;/&lt;span class="kw"&gt;mainClass&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-10"&gt;&lt;a href="#cb1-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &amp;lt;/&lt;span class="kw"&gt;manifest&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-11"&gt;&lt;a href="#cb1-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &amp;lt;/&lt;span class="kw"&gt;archive&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-12"&gt;&lt;a href="#cb1-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;/&lt;span class="kw"&gt;configuration&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb1-13"&gt;&lt;a href="#cb1-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&amp;lt;/&lt;span class="kw"&gt;plugin&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode xml"&gt;&lt;code class="sourceCode xml"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;&amp;lt;!-- Make a standalone build --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&amp;lt;&lt;span class="kw"&gt;plugin&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;groupId&lt;/span&gt;&amp;gt;org.apache.maven.plugins&amp;lt;/&lt;span class="kw"&gt;groupId&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;artifactId&lt;/span&gt;&amp;gt;maven-shade-plugin&amp;lt;/&lt;span class="kw"&gt;artifactId&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;version&lt;/span&gt;&amp;gt;2.2&amp;lt;/&lt;span class="kw"&gt;version&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;executions&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &amp;lt;&lt;span class="kw"&gt;execution&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-8"&gt;&lt;a href="#cb2-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &amp;lt;&lt;span class="kw"&gt;phase&lt;/span&gt;&amp;gt;package&amp;lt;/&lt;span class="kw"&gt;phase&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-9"&gt;&lt;a href="#cb2-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &amp;lt;&lt;span class="kw"&gt;goals&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-10"&gt;&lt;a href="#cb2-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &amp;lt;&lt;span class="kw"&gt;goal&lt;/span&gt;&amp;gt;shade&amp;lt;/&lt;span class="kw"&gt;goal&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-11"&gt;&lt;a href="#cb2-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &amp;lt;/&lt;span class="kw"&gt;goals&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-12"&gt;&lt;a href="#cb2-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &amp;lt;&lt;span class="kw"&gt;configuration&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-13"&gt;&lt;a href="#cb2-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &amp;lt;&lt;span class="kw"&gt;outputFile&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-14"&gt;&lt;a href="#cb2-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ${project.build.directory}/${artifactId}-${version}-standalone.jar&lt;/span&gt;
&lt;span id="cb2-15"&gt;&lt;a href="#cb2-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &amp;lt;/&lt;span class="kw"&gt;outputFile&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-16"&gt;&lt;a href="#cb2-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &amp;lt;/&lt;span class="kw"&gt;configuration&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-17"&gt;&lt;a href="#cb2-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &amp;lt;/&lt;span class="kw"&gt;execution&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-18"&gt;&lt;a href="#cb2-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;/&lt;span class="kw"&gt;executions&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb2-19"&gt;&lt;a href="#cb2-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&amp;lt;/&lt;span class="kw"&gt;plugin&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode xml"&gt;&lt;code class="sourceCode xml"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;&amp;lt;!--  import your local jar--&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&amp;lt;&lt;span class="kw"&gt;dependency&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;groupId&lt;/span&gt;&amp;gt;org.hsqldb&amp;lt;/&lt;span class="kw"&gt;groupId&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;artifactId&lt;/span&gt;&amp;gt;jdbcDriver&amp;lt;/&lt;span class="kw"&gt;artifactId&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;version&lt;/span&gt;&amp;gt;2.4.1&amp;lt;/&lt;span class="kw"&gt;version&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&amp;lt;/&lt;span class="kw"&gt;dependency&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode xml"&gt;&lt;code class="sourceCode xml"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;&amp;lt;!-- create a local respository  --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&amp;lt;&lt;span class="kw"&gt;repositories&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;&lt;span class="kw"&gt;repository&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &amp;lt;&lt;span class="kw"&gt;id&lt;/span&gt;&amp;gt;my-local-repo&amp;lt;/&lt;span class="kw"&gt;id&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &amp;lt;&lt;span class="kw"&gt;url&lt;/span&gt;&amp;gt;file://${basedir}/repos&amp;lt;/&lt;span class="kw"&gt;url&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb4-6"&gt;&lt;a href="#cb4-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &amp;lt;/&lt;span class="kw"&gt;repository&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span id="cb4-7"&gt;&lt;a href="#cb4-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&amp;lt;/&lt;span class="kw"&gt;repositories&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By the way one can add dependency jars by such command line. This
will populate the &lt;em&gt;repos&lt;/em&gt; folder:&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb5-1"&gt;&lt;a href="#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;mvn&lt;/span&gt; org.apache.maven.plugins:maven-install-plugin:2.3.1:install-file&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;-Dfile=lib/hsqldb.jar&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;-DgroupId=&lt;/span&gt;&lt;span class="st"&gt;'org.hsqldb'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;-DartifactId=&lt;/span&gt;&lt;span class="st"&gt;'jdbcDriver'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;-DgeneratePom=true&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-6"&gt;&lt;a href="#cb5-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;-Dpackaging=jar&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-7"&gt;&lt;a href="#cb5-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;-Dversion=2.4.1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-8"&gt;&lt;a href="#cb5-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;-DlocalRepositoryPath=repos&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As a result, the compilation will result as a standalone jar,
containing both local and central dependencies.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Managing local jars with
maven — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/maven-local" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/loading-postgres-from-sqoop</id>
    <title>Loading Postgres from Sqoop</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-06-02&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="loading-postgres-from-sqoop"&gt;Loading Postgres from Sqoop&lt;/h1&gt;
&lt;p&gt;PostgreSQL and Hadoop are complementary technologies. PostgreSQL
outperforms Hadoop to retrieve small amount of information from multiple
tables. Hadoop outperforms PostgreSQL to transform multiple tables into
simplfied and aggregated tables. So, how to load PostgreSQL efficiently
from Hadoop ?&lt;/p&gt;
&lt;h2 id="sqoop-as-a-bridge"&gt;Sqoop as a bridge&lt;/h2&gt;
&lt;p&gt;Hadoop stores data on its distributed filesystem: HDFS. At the end of
the day, the resulting procecced data is stored into a hdfs table and
may need to be loaded into a PosgreSQL table.&lt;/p&gt;
&lt;p&gt;Copy is a efficient a robust PostgreSQL bulkloading function allowing
to load among from others CSV files. It is way faster than a bunch of
parallel prepared insert statements.&lt;/p&gt;
&lt;p&gt;ORC is a efficient and compressed Hadoop data format. It is both
faster to build and to read compared to CSV files.&lt;/p&gt;
&lt;p&gt;As the bridge for Hadoop and relational databases, Sqoop manages all
ORC, CSV, COPY and INSERT methodologies. When dealing with PostgreSQL,
there is no perfect solution.&lt;/p&gt;
&lt;h2 id="sqoop-best-approach"&gt;Sqoop best approach&lt;/h2&gt;
&lt;p&gt;There is two different scenario to load PostgreSQL.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;structured columns&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Sqoop does not allow to use COPY together with ORC tables but only
with CSV. It splits them and run multiple COPY statements from each part
in parallel from HDFS. The CSV format needs to be defined in the sqoop
parameters.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;unstructured columns&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Text information may contain new lines. In this situation, Sqoop is
stuck when it splits the CSV into multiple parts. Yet it is not possible
to use the sqoop direct mode, and the parallel inserts is the only way
to succeed. By chance, it is not necessar to transform the result as
CSV, and it is finally possible to exploit ORC tables as-is.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Writing this post makes me thinking about a potential workaround to
load textual CSV from COPY by using only one mapper in this situation.
Since COPY is highly optimized it is possible that it won't degrade the
performances while making the overall process totally robust.&lt;/p&gt;
&lt;p&gt;EDIT:&lt;/p&gt;
&lt;p&gt;Indeed, using only one mapper allows to handle multiline CSV. Since
COPY is very fast and has been optimized to import dataset into
postgreSQL, in the general case, the method can be generalized to any
kind of CSV to work in any situation. That's the ultimate way to load
PostgreSQL from Hadoop:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;sqoop&lt;/span&gt; export&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--connect &lt;span class="st"&gt;"jdbc:postgresql://&amp;lt;postgres_host&amp;gt;/&amp;lt;postgres_db&amp;gt;"&lt;/span&gt;&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--username &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;postgres_user&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--password-file file:///home/&lt;span class="va"&gt;$USER&lt;/span&gt;/.password&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--export-dir /apps/hive/warehouse/&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my_db&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;/&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my_csv_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a href="#cb1-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--table &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my_postgres_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-7"&gt;&lt;a href="#cb1-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--columns &lt;span class="st"&gt;"id, text_column"&lt;/span&gt;&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-8"&gt;&lt;a href="#cb1-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;-m 1&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-9"&gt;&lt;a href="#cb1-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--direct&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-10"&gt;&lt;a href="#cb1-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--lines-terminated-by &lt;span class="st"&gt;'\n'&lt;/span&gt;&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-11"&gt;&lt;a href="#cb1-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--fields-terminated-by &lt;span class="st"&gt;','&lt;/span&gt;&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-12"&gt;&lt;a href="#cb1-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--input-null-string &lt;span class="st"&gt;"&lt;/span&gt;&lt;span class="dt"&gt;\\\\&lt;/span&gt;&lt;span class="st"&gt;N"&lt;/span&gt;&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-13"&gt;&lt;a href="#cb1-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;--input-null-non-string &lt;span class="st"&gt;"&lt;/span&gt;&lt;span class="dt"&gt;\\\\&lt;/span&gt;&lt;span class="st"&gt;N"&lt;/span&gt;&lt;span class="dt"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-14"&gt;&lt;a href="#cb1-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;-- &lt;span class="at"&gt;--schema&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my_schema&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order to prepare the table ready to be loaded by sqoop, it can be
transformed with a hive sql query:&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;CREATE&lt;/span&gt; &lt;span class="kw"&gt;TABLE&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my_db&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;.&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my_csv_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;STORED &lt;span class="kw"&gt;AS&lt;/span&gt; textfile&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;ROW&lt;/span&gt; FORMAT DELIMITED&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FIELDS TERMINATED &lt;span class="kw"&gt;BY&lt;/span&gt; &lt;span class="st"&gt;','&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;LINES TERMINATED &lt;span class="kw"&gt;BY&lt;/span&gt; &lt;span class="st"&gt;'&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;AS&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-8"&gt;&lt;a href="#cb2-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my_hive_table&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Loading Postgres from Sqoop — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/loading-postgres-from-sqoop" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/eclipse-tips</id>
    <title>Eclipse Tips</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-06-03&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="eclipse-tips"&gt;Eclipse Tips&lt;/h1&gt;
&lt;dl&gt;
&lt;dt&gt;darkest theme&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;simply go throught install menu from this &lt;a href="https://www.eclipse.org/community/eclipse_newsletter/2017/february/article5.php"&gt;link&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl&gt;
&lt;dt&gt;emacs mode&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;select it as a key binding in the preferences. The good point is
emacs shortcuts are also used in most linux terminals. The bad point is
when managing &lt;em&gt;emacs&lt;/em&gt; and &lt;em&gt;vi&lt;/em&gt; is a kind of challenge in
term of reflexes. The next step would be managing both &lt;em&gt;azerty&lt;/em&gt;
and &lt;em&gt;qwerty&lt;/em&gt; keyboards.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Eclipse Tips — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/eclipse-tips" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/nvidia-18.04</id>
    <title>Nvidia &amp;amp; ubuntu 18.04</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-08-19&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="nvidia-ubuntu-18.04"&gt;Nvidia &amp;amp; ubuntu 18.04&lt;/h1&gt;
&lt;p&gt;My new gigabyte aero 14 does ship a nvidia GTX1050. I had several
problem to make it working correctly.&lt;/p&gt;
&lt;h2 id="installation-from-scratch"&gt;Installation from scratch&lt;/h2&gt;
&lt;p&gt;When installing ubuntu from my usb key it simply froze after setup. I
had to enter in maintenance mode, log as root and the resume to get a
VGA screen. After that I was able to install the nvidia drivers by
folowing the steps &lt;a href="https://www.linuxbabe.com/ubuntu/install-nvidia-driver-ubuntu-18-04"&gt;the
folowing steps&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="turning-in-nvidia-mode"&gt;Turning in nvidia mode&lt;/h2&gt;
&lt;p&gt;The command &lt;em&gt;sudo prime-select nvidia&lt;/em&gt; followed by a reboot
makes use of the nvidia chipset. As a result, the powertop tool show a
use of 15W.&lt;/p&gt;
&lt;h2 id="turning-intel-mode"&gt;Turning intel mode&lt;/h2&gt;
&lt;p&gt;The command &lt;em&gt;sudo prime-select intel&lt;/em&gt; followed by a reboot
makes use of the intel chipset. However a bug introduced with 18.04
makes both nvidia and intel running and it uses 20W and worst did not
allow to shutdown/reboot/suspend/hibernate. I ended up by using that &lt;a href="https://www.linuxbabe.com/ubuntu/install-nvidia-driver-ubuntu-18-04"&gt;solution&lt;/a&gt;
which reduce to 7W. Note that I had to make sure the grub was
&lt;em&gt;nouveau.modeset=0 nouveau.runpm=0&lt;/em&gt; in the
&lt;em&gt;/etc/default/grub&lt;/em&gt; file. After installed the &lt;em&gt;tlp&lt;/em&gt; tool I
ended up using 5W.&lt;/p&gt;
&lt;p&gt;Note that I tried &lt;a href="https://bugs.launchpad.net/ubuntu/+source/nvidia-prime/+bug/1765363"&gt;that
other solution&lt;/a&gt; but this resulted in system freeze at reboot.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Nvidia &amp;amp; ubuntu 18.04 — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/nvidia-18.04" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/mutt-aes</id>
    <title>Encrypt &amp;amp; Sign Mails</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-08-25&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="encrypt-sign-mails"&gt;Encrypt &amp;amp; Sign Mails&lt;/h1&gt;
&lt;p&gt;Cacert.org offers validated certificates with a network of trusted
people. That's fun !&lt;/p&gt;
&lt;h2 id="get-a-certificate-eg-cacert.org"&gt;Get a certificate (eg:
CAcert.org)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Client Certificate &amp;gt; new&lt;/li&gt;
&lt;li&gt;add it to Firefox&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key pair can then be extracted in p12 format from Firefox and it
is possible to transform it to rsa format:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;openssl&lt;/span&gt; pkcs12 &lt;span class="at"&gt;-in&lt;/span&gt; ~/Downloads/cacert.p12 &lt;span class="at"&gt;-out&lt;/span&gt; /home/&lt;span class="va"&gt;$USER&lt;/span&gt;/.ssh/id_rsa_cacert&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="installing-neomutt-from-source-on-ubuntu-18.04"&gt;Installing
neomutt from source on Ubuntu 18.04&lt;/h2&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;sudo&lt;/span&gt; apt install libncursesw5-dev&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;sudo&lt;/span&gt; apt install libidn11-dev&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;git&lt;/span&gt; clone https://github.com/neomutt/neomutt&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="bu"&gt;cd&lt;/span&gt; neomutt&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;./configure&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;make&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;sudo&lt;/span&gt; make install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="loading-the-key-into-mutt"&gt;Loading the key into mutt&lt;/h2&gt;
&lt;p&gt;It is necessary to setup and use smime_key command to manage keys. It
will generate a KeyID for the certificate (something like xxxxxx.0)&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;cp&lt;/span&gt; /home/&lt;span class="va"&gt;$USER&lt;/span&gt;/git/neomutt/contrib/smime.rc ~/.smime.rc&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;/usr/libexec/neomutt/smime_keys&lt;/span&gt; init&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;mkdir&lt;/span&gt; &lt;span class="at"&gt;-p&lt;/span&gt; ~/.smime/certificates&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;touch&lt;/span&gt; ~/.smime/certificates/.index&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;mkdir&lt;/span&gt; &lt;span class="at"&gt;-p&lt;/span&gt; ~/.smime/keys&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;touch&lt;/span&gt; ~/.smime/keys/.index&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;/usr/libexec/neomutt/smime_keys&lt;/span&gt; add_p12 ~/Download/cacert.p12&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;/usr/libexec/neomutt/smime_keys&lt;/span&gt; refresh&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Add to &lt;span class="title-ref"&gt;source /home/$USER/.smime.rc&lt;/span&gt;
to .muttrc&lt;/li&gt;
&lt;li&gt;Setup the KeyID in the &lt;em&gt;.smime.rc&lt;/em&gt; file&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="send-a-signed-mail"&gt;Send a signed mail&lt;/h2&gt;
&lt;p&gt;After having written the mail in neomutt type &lt;span class="title-ref"&gt;shift-S&lt;/span&gt; and choose the &lt;span class="title-ref"&gt;s&lt;/span&gt; to sign the mail. It will choose the KeyID by
default, and ask for the key password if exists.&lt;/p&gt;
&lt;h2 id="loading-a-public-key"&gt;Loading a public key&lt;/h2&gt;
&lt;p&gt;Right now, I don't know&lt;/p&gt;
&lt;h2 id="encrypt-a-mail"&gt;Encrypt a mail&lt;/h2&gt;
&lt;p&gt;Choose &lt;span class="title-ref"&gt;e&lt;/span&gt; for encryption, and then
&lt;span class="title-ref"&gt;enter&lt;/span&gt; to list the existing public
keys.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Encrypt &amp;amp; Sign Mails — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/mutt-aes" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/mutt-sidebar</id>
    <title>Mutt &amp;amp; Sidebar</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-08-26&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="mutt-sidebar"&gt;Mutt &amp;amp; Sidebar&lt;/h1&gt;
&lt;p&gt;When receiving many mails a day, having a single mail pool makes easy
to loose important emails. Using mailboxes (ie: sub folders) with rules
becomes a need. The good point is all the mailboxes are regularly
updated to alert when incoming email are received. The few steps are
generating a mailbox tree, mooving mails manually, mooving them
automatically, and finally mooving the history in batch.&lt;/p&gt;
&lt;h2 id="generating-a-mailbox-tree"&gt;Generating a mailbox tree&lt;/h2&gt;
&lt;p&gt;Mailboxes consists of folder{cur, new, old} where &lt;em&gt;folder&lt;/em&gt;
represents its name. The easy way to build them is from the mutt
interface, by pressing &lt;span class="title-ref"&gt;s&lt;/span&gt; on an email and
choosing the new mailboxe name. The root of the mailboxe is defined as
the &lt;span class="title-ref"&gt;folder&lt;/span&gt; variable.&lt;/p&gt;
&lt;h2 id="mooving-mails-manually"&gt;Mooving mails manually&lt;/h2&gt;
&lt;p&gt;It is possible to redirect an email into a mailboxe by pressing &lt;span class="title-ref"&gt;s&lt;/span&gt; and then &lt;span class="title-ref"&gt;=myMailBoxeChoice&lt;/span&gt;. In case you want to put it
back to the general spool just type &lt;span class="title-ref"&gt;=&lt;/span&gt;
with an empty mailboxe.&lt;/p&gt;
&lt;h2 id="mooving-mails-automatically"&gt;Mooving mails automatically&lt;/h2&gt;
&lt;p&gt;I have been able to write rules based on email features such &lt;span class="title-ref"&gt;from&lt;/span&gt; with the &lt;a href="https://userpages.umbc.edu/~ian/procmail.html#tutorial"&gt;helpful
tutorial&lt;/a&gt;. In my setup, &lt;em&gt;getmail&lt;/em&gt; fetches the mails and
invokes &lt;em&gt;procmail&lt;/em&gt; to redirect the mail somewhere. The idea is to
parse the email address with a regex and depending on the result
redirect it in the right &lt;span class="title-ref"&gt;new&lt;/span&gt; mailboxe
folder.&lt;/p&gt;
&lt;h2 id="mooving-mails-history"&gt;Mooving mails history&lt;/h2&gt;
&lt;p&gt;I haven't yet a solution for that.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Mutt &amp;amp; Sidebar — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/mutt-sidebar" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/mutt-notmuch</id>
    <title>Mutt Search on Steroids</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-08-30&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="mutt-search-on-steroids"&gt;Mutt Search on Steroids&lt;/h1&gt;
&lt;p&gt;Mutt has a powerful feature to dig into the history: the
&lt;strong&gt;limit&lt;/strong&gt; feature. By pressing &lt;span class="title-ref"&gt;l&lt;/span&gt; it is then possible to write a query to
filter the mails. It is comparable to the &lt;strong&gt;WHERE&lt;/strong&gt; part of
a SQL statement and allow combining &lt;strong&gt;AND&lt;/strong&gt; operators. In
particular the &lt;strong&gt;~b&lt;/strong&gt; predicate allow to search within the
email's body and the &lt;span class="title-ref"&gt;~X&lt;/span&gt; lets filter
attachments.&lt;/p&gt;
&lt;p&gt;However that feature acts as a &lt;strong&gt;grep&lt;/strong&gt; command and
parse all the mails one by one. Searching in multiple dozen of thousand
emails can last dozen of minutes. Here comes the
&lt;strong&gt;notmuch&lt;/strong&gt; program, that improves greatly the limit
feature with instant search and some other goodies (and also drawbacks).
The secret of this speed is it scan emails and produces a full text
index to be used later.&lt;/p&gt;
&lt;p&gt;The installation is straightforward on ubuntu with &lt;span class="title-ref"&gt;sudo apt install notmuch&lt;/span&gt;. The configuration is
also piece of cake: &lt;span class="title-ref"&gt;notmuch config&lt;/span&gt; will
setup the maildir folder. Later the &lt;span class="title-ref"&gt;notmuch
new&lt;/span&gt; command allows to the mails and can be run again when new
mails arrive. There is also a way to automatize the indexation by setup
system notifications &lt;a href="https://github.com/noah/notmuch-new-inotify"&gt;right there&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The integration in mutt to replace the &lt;em&gt;limit&lt;/em&gt; feature only
need the two rows below in the &lt;em&gt;.muttrc&lt;/em&gt; configuration file.
Pressing &lt;span class="title-ref"&gt;L&lt;/span&gt; will propose to write a query
to filter the mails based on the index &lt;a href="http://log.or.cz/?p=228"&gt;more information here&lt;/a&gt;. To get the
full details on how to search within notmuch: &lt;span class="title-ref"&gt;man notmuch-search-index&lt;/span&gt; describes the syntax
of the search.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# 'L' performs a notmuch query, showing only the results&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;macro&lt;/span&gt; index L &lt;span class="st"&gt;"&amp;lt;enter-command&amp;gt;unset wait_key&amp;lt;enter&amp;gt;&amp;lt;shell-escape&amp;gt;read -p 'notmuch query: ' x; echo &lt;/span&gt;&lt;span class="dt"&gt;\$&lt;/span&gt;&lt;span class="st"&gt;x &amp;gt;~/.cache/mutt_terms&amp;lt;enter&amp;gt;&amp;lt;limit&amp;gt;~i &lt;/span&gt;&lt;span class="dt"&gt;\"\`&lt;/span&gt;&lt;span class="st"&gt;notmuch search --output=messages &lt;/span&gt;&lt;span class="dt"&gt;\$&lt;/span&gt;&lt;span class="st"&gt;(cat ~/.cache/mutt_terms) | head -n 600 | perl -le '@a=&amp;lt;&amp;gt;;chomp@a;s/\^id:// for@a;s/&lt;/span&gt;&lt;span class="dt"&gt;\\&lt;/span&gt;&lt;span class="st"&gt;+/&lt;/span&gt;&lt;span class="dt"&gt;\\\\&lt;/span&gt;&lt;span class="st"&gt;+/g for@a;s/=/&lt;/span&gt;&lt;span class="dt"&gt;\\\\&lt;/span&gt;&lt;span class="st"&gt;=/g for@a;$,=&lt;/span&gt;&lt;span class="dt"&gt;\"&lt;/span&gt;&lt;span class="st"&gt;|&lt;/span&gt;&lt;span class="dt"&gt;\"&lt;/span&gt;&lt;span class="st"&gt;;print@a'&lt;/span&gt;&lt;span class="dt"&gt;\`\"&lt;/span&gt;&lt;span class="st"&gt;&amp;lt;enter&amp;gt;"&lt;/span&gt; &lt;span class="st"&gt;"show only messages matching a notmuch pattern"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# 'a' shows all messages again (supersedes default &amp;lt;alias&amp;gt; binding)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;macro&lt;/span&gt; index a &lt;span class="st"&gt;"&amp;lt;limit&amp;gt;all\n"&lt;/span&gt; &lt;span class="st"&gt;"show all messages (undo limit)"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There is some caveats with notmuch however. Its search within
attachment is not as powerfull as the built-in mutt. In particular, the
later allows to specify the number of attachments. Last but not least,
notmuch does only provide a stemmer for english. That's might be
possible to extend it with an existing implementation of the french
snowball parser.&lt;/p&gt;
&lt;h2 id="edit"&gt;EDIT:&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;mu&lt;/strong&gt; is an alternative to &lt;strong&gt;notmuch&lt;/strong&gt; .
It covers the features described above, and has a better syntax.&lt;/p&gt;
&lt;p&gt;Here is the full documentation there &lt;a href="http://manpages.ubuntu.com/manpages/bionic/man1/mu-find.1.html"&gt;mu
documentation&lt;/a&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# Install&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;sudo&lt;/span&gt; apt install maildir-utils&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# Index Maildir&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;mu&lt;/span&gt; index &lt;span class="at"&gt;-m&lt;/span&gt; my/maildir&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# setup in crontab or use inotify service&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-8"&gt;&lt;a href="#cb2-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-9"&gt;&lt;a href="#cb2-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# to add to .muttrc&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-10"&gt;&lt;a href="#cb2-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# Mode 1.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-11"&gt;&lt;a href="#cb2-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-12"&gt;&lt;a href="#cb2-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# this allows to search into all mailbowes at once&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-13"&gt;&lt;a href="#cb2-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# however, it is a readonly mailbox because off symlinks&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-14"&gt;&lt;a href="#cb2-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;macro&lt;/span&gt; index &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;F8&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;"&amp;lt;shell-escape&amp;gt;mu find --clearlinks --format=links --linksdir=~/Maildir/search "&lt;/span&gt;   &lt;span class="st"&gt;"mu find"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-15"&gt;&lt;a href="#cb2-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;macro&lt;/span&gt; index &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;F9&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;"&amp;lt;change-folder-readonly&amp;gt;~/Maildir/search"&lt;/span&gt;      &lt;span class="st"&gt;"mu find results"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-16"&gt;&lt;a href="#cb2-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-17"&gt;&lt;a href="#cb2-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# Mode 2.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-18"&gt;&lt;a href="#cb2-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-19"&gt;&lt;a href="#cb2-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# this allows to show the 600 first emails&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-20"&gt;&lt;a href="#cb2-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# it is&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-21"&gt;&lt;a href="#cb2-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;macro&lt;/span&gt; index L &lt;span class="st"&gt;"&amp;lt;enter-command&amp;gt;unset wait_key&amp;lt;enter&amp;gt;&amp;lt;shell-escape&amp;gt;read -p 'mu query: ' x; echo &lt;/span&gt;&lt;span class="dt"&gt;\$&lt;/span&gt;&lt;span class="st"&gt;x &amp;gt;~/.cache/mutt_terms&amp;lt;enter&amp;gt;&amp;lt;limit&amp;gt;~i &lt;/span&gt;&lt;span class="dt"&gt;\"\`&lt;/span&gt;&lt;span class="st"&gt;mu find --fields i --quiet 2&amp;gt; /dev/null &lt;/span&gt;&lt;span class="dt"&gt;\$&lt;/span&gt;&lt;span class="st"&gt;(cat ~/.cache/mutt_terms) | head -n 600 | perl -le '@a=&amp;lt;&amp;gt;;chomp@a;s/\^id:// for@a;s/&lt;/span&gt;&lt;span class="dt"&gt;\\&lt;/span&gt;&lt;span class="st"&gt;+/&lt;/span&gt;&lt;span class="dt"&gt;\\\\&lt;/span&gt;&lt;span class="st"&gt;+/g for@a;s/=/&lt;/span&gt;&lt;span class="dt"&gt;\\\\&lt;/span&gt;&lt;span class="st"&gt;=/g for@a;$,=&lt;/span&gt;&lt;span class="dt"&gt;\"&lt;/span&gt;&lt;span class="st"&gt;|&lt;/span&gt;&lt;span class="dt"&gt;\"&lt;/span&gt;&lt;span class="st"&gt;;print@a'&lt;/span&gt;&lt;span class="dt"&gt;\`\"&lt;/span&gt;&lt;span class="st"&gt;&amp;lt;enter&amp;gt;"&lt;/span&gt; &lt;span class="st"&gt;"show only messages matching a mu pattern"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-22"&gt;&lt;a href="#cb2-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# 'a' shows all messages again (supersedes default &amp;lt;alias&amp;gt; binding)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-23"&gt;&lt;a href="#cb2-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;macro&lt;/span&gt; index a &lt;span class="st"&gt;"&amp;lt;limit&amp;gt;all\n"&lt;/span&gt; &lt;span class="st"&gt;"show all messages"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Mutt Search on Steroids — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/mutt-notmuch" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/mutt-vimspell</id>
    <title>Spelling, mutt &amp;amp; vim</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-09-03&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="spelling-mutt-vim"&gt;Spelling, mutt &amp;amp; vim&lt;/h1&gt;
&lt;p&gt;Having a correct spelling is important in society. This is true
specially when come time to write emails.&lt;/p&gt;
&lt;p&gt;Here is a trick to activate vim spelling while editing email in
&lt;strong&gt;mutt&lt;/strong&gt;. Add the following line into your .muttrc
configuration file:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="bu"&gt;set&lt;/span&gt; editor=&lt;span class="st"&gt;"vim -c 'set textwidth=72' -c':set spell' -c':setlocal spell spelllang=en_us'"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This allows to check English spelling correctly.&lt;/p&gt;
&lt;p&gt;Enjoy !&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Spelling, mutt &amp;amp; vim — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/mutt-vimspell" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/email-best-practices</id>
    <title>Email Best Practices</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-09-03&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="email-best-practices"&gt;Email Best Practices&lt;/h1&gt;
&lt;p&gt;I will post here all best practices about writing emails. A lot of
useful information can be found &lt;a href="https://www.ietf.org/rfc/rfc3676.txt"&gt;there&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="writing-email"&gt;Writing email&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Choose an email object&lt;/p&gt;
&lt;p&gt;For example this pattern is great: &lt;strong&gt;[Action] Topic&lt;/strong&gt;.
&lt;strong&gt;Action&lt;/strong&gt; to help your recipient to understand what you
want from him. &lt;strong&gt;topic&lt;/strong&gt; is a small synthesis of the topic
in which the action is supposed to happen. This pattern has been advised
by Michael Kahn.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep the body narrow&lt;/p&gt;
&lt;p&gt;The email should not size more than 72 character width. This improve
readability specially on small screen. In vim, the width can be setup,
and the shorkey &lt;strong&gt;g+q&lt;/strong&gt; on a visual selection makes things
easy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="reply-to-email"&gt;Reply to email&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Reply below your recipient&lt;/p&gt;
&lt;p&gt;Bottom Posting (BP) is answering bellow the previous email as
opposite to Top Posting (TP) aka gmail way of doing. BP has many
advantages over TP. BP allows to read the emails in the natural order ;
specially for people who discover the thread. &lt;a href="http://www.idallen.com/topposting.html"&gt;more information here&lt;/a&gt;
Keep an empty row between the previous answer and yours for
readability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove information&lt;/p&gt;
&lt;p&gt;Remove the recipient signature, out of context content. In
particular, do not keep the recipient email within the email body for
security reasons.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Append your signature&lt;/p&gt;
&lt;p&gt;A signature is generally on the bottom of the email, preceded by a
row containing: &lt;em&gt;--&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sign the email&lt;/p&gt;
&lt;p&gt;Sign the email with your AES private key as a proof of your
identity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mask your mailing system&lt;/p&gt;
&lt;p&gt;Email can store the &lt;strong&gt;User-agent&lt;/strong&gt; field. This can be
found in the header of the email and may share precious information such
your operating system and its version. eg: &lt;strong&gt;User-Agent:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101
Thunderbird/52.3.0&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="mailing-list"&gt;Mailing List&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Email the mailing list &lt;strong&gt;only&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Remove the previous writer. In any cases, he will receive the email
since he subscribed to the list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a dedicated alias&lt;/p&gt;
&lt;p&gt;Mailing list are usually public and this you will probably end up
with spam. A good trick is to use an alias combined with a rule such:
"message directed to the alias goes into the trash". Riseup.net provides
alias email.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Email Best Practices — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/email-best-practices" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/hive-llap-resource</id>
    <title>Hive Llap</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-09-07&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="hive-llap"&gt;Hive Llap&lt;/h1&gt;
&lt;h2 id="resource-consumption"&gt;Resource consumption&lt;/h2&gt;
&lt;p&gt;Hive llap is quite complicated to tune.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;hive.llap.daemon.task.scheduler.enable.preemption=true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="https://community.hortonworks.com/articles/149486/llap-sizing-and-setup.html"&gt;a
great article&lt;/a&gt;&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Hive Llap — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/hive-llap-resource" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/archlinux-pg11</id>
    <title>Postgresql 11 on Archlinux</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-09-27&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="postgresql-11-on-archlinux"&gt;Postgresql 11 on Archlinux&lt;/h1&gt;
&lt;p&gt;I am fairly new to archlinux. Postgresql 11 is fairly new too. Here
are the steps to install that version.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# get the lattest postgres in the repos&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# avoid checking for sha fingerprint, because not the same version&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;yaourt&lt;/span&gt; &lt;span class="at"&gt;--m-arg&lt;/span&gt; &lt;span class="st"&gt;"--skipchecksums --skippgpcheck"&lt;/span&gt; &lt;span class="at"&gt;-Sb&lt;/span&gt; postgresql&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# 1. edit the PKGBUILD file, change to 11.0 version&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# 2. comment the check() part&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a href="#cb1-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# 3. after building and installing, change to 11 the PGMAJORVERSION within:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-7"&gt;&lt;a href="#cb1-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;sudo&lt;/span&gt; vim /usr/bin/postgresql-check-db-dir&lt;/span&gt;
&lt;span id="cb1-8"&gt;&lt;a href="#cb1-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# make the link for psql command working&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-9"&gt;&lt;a href="#cb1-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;sudo&lt;/span&gt; ln &lt;span class="at"&gt;-s&lt;/span&gt; /usr/lib/libreadline.so.7 /usr/lib/libreadline.so.6&lt;/span&gt;
&lt;span id="cb1-10"&gt;&lt;a href="#cb1-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# install that old version to make posgres command work&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-11"&gt;&lt;a href="#cb1-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;yaourt&lt;/span&gt; &lt;span class="at"&gt;-S&lt;/span&gt; icu54&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That's all. By the way, I do not have any idea right now on how to
upgrade minor versions in the future, but I will employ myself to update
this post.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Postgresql 11 on Archlinux — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/archlinux-pg11" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/deploying-with-githup-pages</id>
    <title>Deploying Nikola with Githup
Pages</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-11-11&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="deploying-nikola-with-githup-pages"&gt;Deploying Nikola with Githup
Pages&lt;/h1&gt;
&lt;h2 id="the-simple-way"&gt;The simple way&lt;/h2&gt;
&lt;p&gt;Its about using the &lt;em&gt;docs&lt;/em&gt; github pages method.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;create a new github repository&lt;/li&gt;
&lt;li&gt;create a &lt;em&gt;/docs/&lt;/em&gt; folder with the website in it&lt;/li&gt;
&lt;li&gt;enable github pages and specify the &lt;em&gt;docs&lt;/em&gt; folder as html
source&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="why-the-simple-way"&gt;Why the simple way&lt;/h2&gt;
&lt;p&gt;The alternate way is to use a &lt;em&gt;gh-pages&lt;/em&gt; branch to store the
website. The main problem is the method leads to highly complex
deployment method with &lt;a href="http://www.damian.oquanta.info/posts/one-line-deployment-of-your-site-to-gh-pages.html"&gt;git
subtree&lt;/a&gt; or &lt;a href="https://www.asmeurer.com/blog/posts/moving-to-github-pages-with-nikola/"&gt;other
way&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A second problem is this method make either duplicate website source
code, or makes building the website for each post.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Deploying Nikola with Githup
Pages — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/deploying-with-githup-pages" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/a-decent-python-configuration</id>
    <title>A decent python
configuration</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-11-11&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="a-decent-python-configuration"&gt;A decent python
configuration&lt;/h1&gt;
&lt;h2 id="use-anaconda"&gt;Use Anaconda&lt;/h2&gt;
&lt;p&gt;Anaconda allows to have multiple python versions. This is much easier
than using &lt;em&gt;virtualenv&lt;/em&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;conda&lt;/span&gt; env list &lt;span class="co"&gt;# lists all envs&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;conda&lt;/span&gt; env create py3.5 pip setuptools python=3.5 &lt;span class="co"&gt;# create a python env&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;conda&lt;/span&gt; activate py3.5 &lt;span class="co"&gt;# activate the latter&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;conda&lt;/span&gt; deactivate &lt;span class="co"&gt;# deactivate it&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;conda&lt;/span&gt; env remove &lt;span class="at"&gt;-n&lt;/span&gt; py3.5 &lt;span class="co"&gt;# remove it completely&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="use-pip-together-with-anaconda"&gt;Use pip together with
anaconda&lt;/h2&gt;
&lt;p&gt;The package will be installed within the environement. pip has a much
broader list of packages than the anaconda channel.&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;pip&lt;/span&gt; install &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my-package&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; # install a package&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;pip&lt;/span&gt; install &lt;span class="at"&gt;--index-url&lt;/span&gt; https://pypi.org/simple/ &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my-package&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; # specify the repository&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;pip&lt;/span&gt; install . &lt;span class="co"&gt;# a local package&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;pip&lt;/span&gt; remove &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;my-package&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;  # remove it&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=A decent python
configuration — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/a-decent-python-configuration" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/pyspark-considerations</id>
    <title>Extracting raw data from
hdfs</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-11-22&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="extracting-raw-data-from-hdfs"&gt;Extracting raw data from
hdfs&lt;/h1&gt;
&lt;p&gt;I have tested multiple ways to get data from hdfs. There is two
situations:&lt;/p&gt;
&lt;h2 id="the-data-fits-in-a-local-node-ram-memory"&gt;The data fits in a
local node RAM memory:&lt;/h2&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# will produce a local csv&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sql(&lt;span class="st"&gt;"select * from my_table where true"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    .toPandas()&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    .to_csv(&lt;span class="st"&gt;"myLocalFile.csv"&lt;/span&gt;, encoding&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"utf8"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# otherwise spark shell keeps running&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a href="#cb1-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;exit(&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# run the python script:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="va"&gt;PYTHONSTARTUP&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;my/python/path/prog.py &lt;span class="ex"&gt;pyspark&lt;/span&gt; &lt;span class="at"&gt;--master&lt;/span&gt; yarn [...]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="the-dataset-does-not-fit-into-ram-memory"&gt;The dataset does not
fit into RAM memory:&lt;/h2&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# will produce some csv on hdfs&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sql(&lt;span class="st"&gt;"select * from my_table where true"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    .write()&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    .&lt;span class="bu"&gt;format&lt;/span&gt;(&lt;span class="st"&gt;"csv"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    .save(&lt;span class="st"&gt;"/output/dir/on/hdfs/"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# otherwise spark shell keeps running&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;exit(&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# run the python script:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="va"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;my/python/path/prog.py &lt;span class="ex"&gt;pyspark&lt;/span&gt; &lt;span class="at"&gt;--master&lt;/span&gt; yarn [...]&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# merge the files on the local filesystem&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;hadoop&lt;/span&gt; fs &lt;span class="at"&gt;-getmerge&lt;/span&gt; /output/dir/on/hdfs/ /desired/local/output/file.csv&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Extracting raw data from
hdfs — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/pyspark-considerations" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/rendering-patients-in-solr</id>
    <title>Rendering Patients in SolR
(part-1)</title>
    <updated>2021-11-07T15:49:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-12-02&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="rendering-patients-in-solr-part-1"&gt;Rendering Patients in SolR
(part-1)&lt;/h1&gt;
&lt;p&gt;Patient medical records contain a broad variety of data such numeric,
coding, time-series or medical reports. It can be translated as a json
document with a nested structure.&lt;/p&gt;
&lt;p&gt;SolR allows to handle highly nested objects to be queried
efficiently. It provides pagination, and also faceting features wich are
very powerful to provide a patient centered search engine.&lt;/p&gt;
&lt;p&gt;Patients in electronic health records:&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/patient_nested.webp" class="align-center" style="width:200.0%" alt="Patient Nested"&gt;&lt;/p&gt;
&lt;p&gt;Consider the two patients below:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1" data-code="json

"&gt;&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It yet possible to ask relevant questions to SolR:&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# Count and give me one patient having during the same visit:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# - one XX1 code&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# - one report containing "popeye"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;curl&lt;/span&gt; http://localhost:8983/solr/patient/query &lt;span class="at"&gt;-d&lt;/span&gt; &lt;span class="st"&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;q=*:*&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;&amp;amp;fq={!parent which="content_type_s:visite"}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;    ccam_ss:XX1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-8"&gt;&lt;a href="#cb2-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;&amp;amp;fq={!parent which="content_type_s:visite"}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-9"&gt;&lt;a href="#cb2-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;    {!complexphrase inOrder=true}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-10"&gt;&lt;a href="#cb2-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;        doc_text_t:"popeye marche"~3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-11"&gt;&lt;a href="#cb2-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;        AND doc_type_ss:APHP.CRH-H&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-12"&gt;&lt;a href="#cb2-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;&amp;amp;fl=id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-13"&gt;&lt;a href="#cb2-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;&amp;amp;rows=1'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using blockJoin queries has some limitations: - it is not possible to
highlight matching text from a parent or a child document - it has some
impact on performances&lt;/p&gt;
&lt;p&gt;The particular model used in this post has some limitations: - it is
not possible to highlight matching text at the patient level - it is not
possible to play with a sequence of events, such of encounter - queries
are complicated&lt;/p&gt;
&lt;p&gt;Let's see a other approach in a next post.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Rendering Patients in SolR
(part-1) — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-11-07 15:49&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/rendering-patients-in-solr" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/rendering-patients-in-solr-part-2</id>
    <title>Rendering Patients in SolR
(part-2)</title>
    <updated>2021-11-07T15:49:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-12-04&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="rendering-patients-in-solr-part-2"&gt;Rendering Patients in SolR
(part-2)&lt;/h1&gt;
&lt;p&gt;A patient search engine needs to meet several criteria: #. blazing
fast #. handle both structured and unstructured data #. for free text
retrieval: include NLP pipelines results #. define complex sequence of
events, on patient, and/or encounter level #. highlight results&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://parisni.github.io/weblog/posts/rendering-patients-in-solr"&gt;previous
post&lt;/a&gt; was a first attempt to modelize a patient in SolR. While it
offered solution for the three first crieteria, it was ineficient to
provide event based reasonning and also highlighting results. The below
method tries to answer more elegantly the question.&lt;/p&gt;
&lt;p&gt;The idea is to modelize the patient as a list of nested encounters
with the last encounter beeing the first and vice-versa. Each encounter
object being a flat and denormalized document. The design allows to
reason sequence of events and also to highlight the part of the texts
that match the query.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/encounter_nested.webp" class="align-center" style="width:200.0%" alt="Encounter Nested"&gt;&lt;/p&gt;
&lt;p&gt;The denormalization has several advantages in SolR such speading up
the queries and also simplifying them. By combining multivalued texts
fields and path based text values the design pattern offers power and
simplicity. An other aspect of denormalization is to repeat the patient
demographic information in each encounter, to enable filtering on this
level, and also faceting on patients details.&lt;/p&gt;
&lt;p&gt;Having nested encounters allows reasoning on sequence of event by
using blockJoin. Indeed this offers the opportunity to add query filter
based on childs. The idea is to add a level in each encounter by
counting the number of days from the last encounter. It is yet possible
to ask for: A patient having a breast cancer and whoom had a chirurgical
mamal implant within the 2 years.&lt;/p&gt;
&lt;p&gt;One drawback of this design is it does not bring back patients but
encounters. One solution is to use faceting capabilities to count the
number of unique patients within the cohort.&lt;/p&gt;
&lt;p&gt;EDIT: The method has been disapointing:&lt;/p&gt;
&lt;p&gt;#. a parent object shall have a different nature than childs. It is
then not possible make a be a parent at any level of the chain. #. only
a parent object can be highlighted. While it is possible to reason on
childs content, it is not possible to highlight them&lt;/p&gt;
&lt;p&gt;Let's invent a better method&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Rendering Patients in SolR
(part-2) — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-11-07 15:49&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/rendering-patients-in-solr-part-2" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/rendering-patients-in-solr-part-3</id>
    <title>Rendering Patients in SolR
(part 3)</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-12-13&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="rendering-patients-in-solr-part-3"&gt;Rendering Patients in SolR
(part 3)&lt;/h1&gt;
&lt;p&gt;The two previous attempts have failed to bring enough power and
flexibility in searching within patient history.&lt;/p&gt;
&lt;p&gt;The current approach allows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;highlighting&lt;/em&gt; all the relevant information at the encounter
level&lt;/li&gt;
&lt;li&gt;mixing &lt;em&gt;logical operators&lt;/em&gt; (OR,AND,NOT) between
encounters&lt;/li&gt;
&lt;li&gt;mixing &lt;em&gt;temporal order&lt;/em&gt; between encounters&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;First the process of building cohorts changes to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;define the constraints on one encounter&lt;/li&gt;
&lt;li&gt;eventually add patient level constraints&lt;/li&gt;
&lt;li&gt;look for those matching encounters&lt;/li&gt;
&lt;li&gt;loop 1. to 3. to define other encounters&lt;/li&gt;
&lt;li&gt;add logical links between encounters/groups&lt;/li&gt;
&lt;li&gt;add temporal links between encounters/groups&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A constraint on a encounter might be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a date&lt;/li&gt;
&lt;li&gt;a delay&lt;/li&gt;
&lt;li&gt;a number&lt;/li&gt;
&lt;li&gt;a code&lt;/li&gt;
&lt;li&gt;a code and a number&lt;/li&gt;
&lt;li&gt;a code and a date&lt;/li&gt;
&lt;li&gt;a complex natural langage query&lt;/li&gt;
&lt;li&gt;a sequence of events&lt;/li&gt;
&lt;li&gt;a combination of all of them (AND,OR,NOT)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Constrained encounters can be then linked together. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;encounterA: (37°C) =&amp;gt; temp:37&lt;/li&gt;
&lt;li&gt;encounterB: (36°C) =&amp;gt; temp:36&lt;/li&gt;
&lt;li&gt;encounterC: (35°C) =&amp;gt; temp:35&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;encounterA AND encounterB (where encounterA = encounterB is
possible)&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37)&amp;amp;fq={!parent
which="type:encounter"}(temp:36)&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;encounterA OR encounterB&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37) OR (temp:36)&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;encounterA BEFORE encounterB&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37 AND
old.temp:36)&amp;amp;fq=(temp:36)&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;(encounterA AND encounterB) BEFORE encounterC&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37)&amp;amp;fq={!parent
which="type:encounter"}(temp:36)&amp;amp;fq={!parent
which="type:encounter"}(temp:37 AND old.temp:35)&amp;amp;fq={!parent
which="type:encounter"}(temp:36 AND old.temp:35)&amp;amp;fq={!parent
which="type:encounter"}(temp:35)&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;encounterA AND encounterB (where encounterA != encounterB)&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37 AND old.temp:36) OR
(temp:36 AND old.temp:37)&amp;amp;fq={!parent
which="type:encounter"}(temp:36)&amp;amp;fq={!parent
which="type:encounter"}(temp:37)&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;(encounterA AND encounterB) BEFORE encounterC (where encounterA !=
encounterB)&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37 AND old.temp:36) OR
(temp:36 AND old.temp:37)&amp;amp;fq={!parent
which="type:encounter"}(temp:36)&amp;amp;fq={!parent
which="type:encounter"}(temp:37)&amp;amp;fq={!parent
which="type:encounter"}(temp:37 AND old.temp:35)&amp;amp;fq={!parent
which="type:encounter"}(temp:36 AND old.temp:35)&amp;amp;fq={!parent
which="type:encounter"}(temp:35)&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="sacrifices"&gt;Sacrifices&lt;/h2&gt;
&lt;p&gt;To enable the temporal/disjoint feature the documents are repeated in
a factorial way. This may lead to terrible situations. Only the textual
data should be stored. Moreover in each document, the historical
information should only be indexed and not stored. Even by doing this
the dimention of the index might be unreasonnable. An other problem is
the complexity to produce such documents: the serialization to json
might be a nightmare.&lt;/p&gt;
&lt;h2 id="less-ambitions"&gt;Less Ambitions&lt;/h2&gt;
&lt;p&gt;By not enabling temporal/disjoint, what append's?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;encounterA: (37°C) =&amp;gt; temp:37&lt;/li&gt;
&lt;li&gt;encounterB: (36°C) =&amp;gt; temp:36&lt;/li&gt;
&lt;li&gt;encounterC: (35°C) =&amp;gt; temp:35&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;encounterA AND encounterB (where encounterA = encounterB is
possible)&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37)&amp;amp;fq={!parent
which="type:encounter"}(temp:36)&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;encounterA OR encounterB&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37) OR (temp:36)&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;(encounterA OR encounterB) AND encounterC&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37) OR
(temp:36)&amp;amp;fq={!parent which="type:encounter"}(temp:35)&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;(encounterA OR encounterB) NOT encounterC&lt;/dt&gt;
&lt;dd&gt;
&lt;ul&gt;
&lt;li&gt;fq={!parent which="type:encounter"}(temp:37) OR
(temp:36)&amp;amp;fq=-_&lt;a href=""&gt;query&lt;/a&gt;:"{!parent
which="type:encounter"}(temp:35)"&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Rendering Patients in SolR
(part 3) — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/rendering-patients-in-solr-part-3" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/multi-word-synonyms-in-solr</id>
    <title>Multiword synomyms in SolR</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-12-14&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;3 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="multiword-synomyms-in-solr"&gt;Multiword synomyms in SolR&lt;/h1&gt;
&lt;p&gt;Medical domain has multiple ways to tell about the same thing. It
becomes handy to use and maintain muliword synonyms thesauri.&lt;/p&gt;
&lt;p&gt;SolR recently released a built-in solution to handle multi-word
synonyms and I have tested it successfully:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;synonyms are computed at query time &lt;strong&gt;only&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;using multi-word synonyms are only compatible with
simple/lucene/eDismax query parsers right now.
&lt;strong&gt;complexphrase&lt;/strong&gt; is broken with such dictionary.&lt;/li&gt;
&lt;li&gt;multi-word synonyms are supposed to be used &lt;strong&gt;before
stemming&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;adding new synonyms needs to delete the collection and reindex it.
(to be confirmed)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some questions remains: 1) How many synonyms can solr handle and
still perform well ? 2) How to make synonyms addition/modifications
without rebooting ? 3) Which is the better query parser together with
multi-word synonyms ?&lt;/p&gt;
&lt;h2 id="the-simple-query-parser"&gt;The simple query parser&lt;/h2&gt;
&lt;p&gt;Given this field: &lt;em&gt;text:"say me bye or say hello world"&lt;/em&gt; And
the given configuration:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode xml"&gt;&lt;code class="sourceCode xml"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&amp;lt;&lt;span class="kw"&gt;example&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;one word &lt;strong&gt;text:(hello)&lt;/strong&gt; matches &lt;strong&gt;"say me bye
or say &amp;lt;em&amp;gt;hello&amp;lt;/em&amp;gt; world"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;one regex &lt;strong&gt;text:(/hel.&lt;/strong&gt;/)** matches &lt;strong&gt;"say me
bye or say &amp;lt;em&amp;gt;hello&amp;lt;/em&amp;gt; world"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;not one word &lt;strong&gt;text:(hello)&lt;/strong&gt; matches &lt;strong&gt;"say me
bye or say &amp;lt;em&amp;gt;hello&amp;lt;/em&amp;gt; world"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;one tailing wildcard &lt;strong&gt;text:(&lt;/strong&gt;o)** matches
&lt;strong&gt;"say me bye or say &amp;lt;em&amp;gt;hello&amp;lt;/em&amp;gt;
world"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;one fuzzy word &lt;strong&gt;text:(word~)&lt;/strong&gt; matches &lt;strong&gt;"say me
bye or say hello &amp;lt;em&amp;gt;world&amp;lt;/em&amp;gt;"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;two words &lt;strong&gt;text:(hello AND bye)&lt;/strong&gt; matches &lt;strong&gt;"say
me &amp;lt;em&amp;gt;bye&amp;lt;/em&amp;gt; or say &amp;lt;em&amp;gt;hello&amp;lt;/em&amp;gt;
world"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;two words exact &lt;strong&gt;text:("hello world")&lt;/strong&gt; matches
&lt;strong&gt;"say me bye or say &amp;lt;em&amp;gt;hello&amp;lt;/em&amp;gt;
&amp;lt;em&amp;gt;world&amp;lt;/em&amp;gt;"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;two words with distance &lt;strong&gt;text:("say world"~2)&lt;/strong&gt;
matches &lt;strong&gt;"say me bye or &amp;lt;em&amp;gt;say&amp;lt;/em&amp;gt; hello
&amp;lt;em&amp;gt;world&amp;lt;/em&amp;gt;"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;one word AND two words with distance &lt;strong&gt;text:(bye AND "hello
world"~2)&lt;/strong&gt; matches &lt;strong&gt;"say me &amp;lt;em&amp;gt;bye&amp;lt;/em&amp;gt; or
say &amp;lt;em&amp;gt;hello&amp;lt;/em&amp;gt; &amp;lt;em&amp;gt;world&amp;lt;/em&amp;gt;"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;two words with distance AND two words with distance
&lt;strong&gt;text:("say bye"~2 AND "say world"~2)&lt;/strong&gt; matches
&lt;strong&gt;"&amp;lt;em&amp;gt;say&amp;lt;/em&amp;gt; me &amp;lt;em&amp;gt;bye&amp;lt;/em&amp;gt; or
&amp;lt;em&amp;gt;say&amp;lt;/em&amp;gt; hello &amp;lt;em&amp;gt;world&amp;lt;/em&amp;gt;"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;one multi-word synonym: &lt;strong&gt;text:("see you soon"~2 AND "hello
world"~2)&lt;/strong&gt; matches &lt;strong&gt;"say me &amp;lt;em&amp;gt;bye&amp;lt;/em&amp;gt; or
say &amp;lt;em&amp;gt;hello&amp;lt;/em&amp;gt; &amp;lt;em&amp;gt;world&amp;lt;/em&amp;gt;"&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: The simple query parser has some limations compared to the
complexphrase parser:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it only keeps order for exact phrases&lt;/li&gt;
&lt;li&gt;fuzzy, joker are not allowed for phrases&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However it has some advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it allows to define multiple groups of words&lt;/li&gt;
&lt;li&gt;it allows regex on one word&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-to-handle-negation"&gt;How to handle negation&lt;/h2&gt;
&lt;p&gt;SolR allows to look for &lt;em&gt;the absence&lt;/em&gt; of a word or phrase, but
not for negations of them. One solution I found is to exploit the
multi-word synonyms, by linking all the various ways to express negation
to the &lt;em&gt;neg&lt;/em&gt; word. Then it is possible to ask for the absence of
a negation.&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;never&lt;/span&gt; had,never had any, has no, not, no anymore =&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; neg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This can be used in this way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"text": "I never had any trouble"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;searching for people with trouble: &lt;em&gt;text:((trouble) AND NOT ("neg
trouble"))&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="generalisation-of-negation"&gt;Generalisation of negation&lt;/h1&gt;
&lt;p&gt;For a given &lt;em&gt;simple full-text&lt;/em&gt; low level filter such a word or
a phrase:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;simple&lt;/em&gt; =&amp;gt; &lt;em&gt;(simple AND NOT "neg simple")&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"very simple"&lt;/em&gt; =&amp;gt; &lt;em&gt;("very simple" AND NOT "neg very
simple)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;less simple&lt;/em&gt; =&amp;gt; &lt;em&gt;( (less AND NOT "neg less") OR
(simple AND NOT "neg simple) )&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;less AND simple&lt;/em&gt; =&amp;gt; &lt;em&gt;( (less AND NOT "neg less") AND
(simple AND NOT "neg simple) )&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="simplifying-interface-for-user"&gt;Simplifying interface for
user&lt;/h1&gt;
&lt;p&gt;The more user friendly interface in my mind would allo people to
write group of words and articulate them with logical operator such
AND/OR/NOT. You don't want them to manage phrase and word too. So when a
user look for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;see you soon&lt;/em&gt; =&amp;gt; &lt;em&gt;"see you soon"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They might check for ordered and compacted word, but by default we
the tolerate some distance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;see you soon&lt;/em&gt; =&amp;gt; &lt;em&gt;"see you soon"&lt;/em&gt; =&amp;gt; &lt;em&gt;"see
you soon"~4&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In order to remove negated pattern, we apply the above method:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;see you soon&lt;/em&gt; =&amp;gt; &lt;em&gt;"see you soon"&lt;/em&gt; =&amp;gt; &lt;em&gt;"see
you soon"~4&lt;/em&gt; =&amp;gt; &lt;em&gt;"see you soon"~4 AND NOT "neg see you
soon"~4&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;People might add other groups and articulate them together:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;("see you soon"~4 AND NOT "neg see you soon"~4) NOT ("an other
example"~4 AND NOT "neg an other example"~4)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above example would match a text containing &lt;em&gt;see you soon&lt;/em&gt;
and not containing &lt;em&gt;an other example&lt;/em&gt;. By the way any multi-word
synonym would be translated. This also means the user not able to use
jocker or fuzzy search. However, the jocker can be replaced with the
&lt;em&gt;stemming&lt;/em&gt; process, which has the advantage of not breaking the
performances in case of very narrow joker query and also being
transparent for the end user. There is also a possible replacement for
fuzzy feature transparent to user.&lt;/p&gt;
&lt;h2 id="fuzzy-search-with-synonyms"&gt;Fuzzy search with synonyms&lt;/h2&gt;
&lt;p&gt;Word Embedding offers the opportunity to freely produce typo
synonyms. I have tested succesfully a quite large list of them (~200k
entries) and the performances where not impacted. So most common error
are transparently integrated to end users.&lt;/p&gt;
&lt;h2 id="dated-delay-and-other-structured-informations"&gt;Dated, Delay and
other structured informations&lt;/h2&gt;
&lt;p&gt;The simple query parser let add some structured informations within
the free-text to be queried. For example the below enriched text
allows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"text":"delay0002 dateCreat20181214 my example
free-text"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;text:([delay0001 TO delay0003] AND [dateCreat201812 TO NOW] AND
"example")&lt;/em&gt; this makes possible to filter based on dates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is also possible to add many coded informations within the text to
be queried as structured data with full-text structured capabilities.
This will be very useful to get NLP pipelines results.&lt;/p&gt;
&lt;h2 id="dealing-with-multivalued-fields-mv"&gt;Dealing with multivalued
fields (MV)&lt;/h2&gt;
&lt;p&gt;While the MVs look temptating for storing multiple occurence of the
same concept, they are not a good choice when dealing with full text
queries. Indeed the multiple values are not considered as independant
values but as a whole with some defined distance between values.&lt;/p&gt;
&lt;p&gt;So how to modelize multiple occurences of the same concept within
SolR ? One alternate solution is to use multiple single fields for
textual datatype. For example it the encounter has two physician notes
both with a adverse event section, the resulting encounter document will
have two fields "pn.adverse1" and "pn.averse2". This implies that when
the user asks for something present into this section, the resulting
query should be modified accordingly&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"pn.adverse1":"hello world"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"pn.adverse2":"my example"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"pn.adverse:(hello AND example)"&lt;/em&gt; will be replaced by:&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"pn.adverse1:(hello AND example) OR pn.adverse2:(hello AND
example)"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This makes also possible to mix full text queries with structured
queries based on the same field. Also there is some drawbacks. The
replacement mecanism makes mandatory to know in advance the maximum
number of fields of every documents. An other drawback is when the user
wants to look into every section of the same document. One solution is
to copyField&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The final method offers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;multi-word synonyms&lt;/li&gt;
&lt;li&gt;monoword synonyms&lt;/li&gt;
&lt;li&gt;monoword typos (fuzzy match)&lt;/li&gt;
&lt;li&gt;stemming&lt;/li&gt;
&lt;li&gt;negation&lt;/li&gt;
&lt;li&gt;AND/OR/NOT operators&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Still some aspects are missing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;no weighted queries (but not needed for my use case)&lt;/li&gt;
&lt;li&gt;no multivalued textual fields (this parser does not make difference
between them)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This lets envisage a simple but powerful interface. Let's now see how
to transform a medical relational database and populate SolR.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Multiword synomyms in SolR — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/multi-word-synonyms-in-solr" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/mixing-spark-and-solr</id>
    <title>Mixing Spark and SolR</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-12-17&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;2 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="mixing-spark-and-solr"&gt;Mixing Spark and SolR&lt;/h1&gt;
&lt;p&gt;The spark-solr library makes it possible to interact with SolR-Cloud
- it is not compatible with SolR standalone. It allows both
&lt;em&gt;reading&lt;/em&gt; and &lt;em&gt;writing&lt;/em&gt; within SolR.&lt;/p&gt;
&lt;h2 id="reading-from-solr"&gt;Reading from SolR&lt;/h2&gt;
&lt;p&gt;The library implements the &lt;em&gt;export&lt;/em&gt; features which is fast to
retrieve DocValues enabled columns.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode scala"&gt;&lt;code class="sourceCode scala"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// configure the access&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; options &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="ex"&gt;Map&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt; &lt;span class="st"&gt;"collection"&lt;/span&gt; &lt;span class="op"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;"gettingstarted"&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"zkhost"&lt;/span&gt; &lt;span class="op"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;"localhost:9983"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// use export to boost the retrieval&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// choose fields and the query&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;spark&lt;span class="op"&gt;.&lt;/span&gt;read&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;format&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"solr"&lt;/span&gt;&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;options&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;options&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;option&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"request_handler"&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"/export"&lt;/span&gt;&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;option&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"fields"&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="st"&gt;"id"&lt;/span&gt;&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;option&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"query"&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="st"&gt;"id:/.*.pdf/"&lt;/span&gt;&lt;span class="op"&gt;).&lt;/span&gt;load&lt;span class="op"&gt;.&lt;/span&gt;count&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="writing-from-spark"&gt;Writing from Spark&lt;/h2&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode scala"&gt;&lt;code class="sourceCode scala"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;csvDF&lt;span class="op"&gt;.&lt;/span&gt;write&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;format&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"solr"&lt;/span&gt;&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;options&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;options&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;mode&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;org&lt;span class="op"&gt;.&lt;/span&gt;apache&lt;span class="op"&gt;.&lt;/span&gt;spark&lt;span class="op"&gt;.&lt;/span&gt;sql&lt;span class="op"&gt;.&lt;/span&gt;SaveMode&lt;span class="op"&gt;.&lt;/span&gt;Overwrite&lt;span class="op"&gt;).&lt;/span&gt;save&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="creating-json-from-spark"&gt;Creating JSON from Spark&lt;/h2&gt;
&lt;p&gt;Many useful sql functions to build json from spark exist. So far, I
have been using &lt;em&gt;to_json&lt;/em&gt;, &lt;em&gt;named_stuct&lt;/em&gt;, &lt;em&gt;map&lt;/em&gt;,
&lt;em&gt;map_from_entries&lt;/em&gt; and &lt;em&gt;concat_map&lt;/em&gt; with some success.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generate a json object with zero to many items&lt;/strong&gt;, from
zero to many rows:&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;tmp &lt;span class="kw"&gt;as&lt;/span&gt; (&lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;id&lt;/span&gt;,&lt;span class="st"&gt;'sec1'&lt;/span&gt; sec,&lt;span class="st"&gt;'a'&lt;/span&gt; cont&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;union&lt;/span&gt; &lt;span class="kw"&gt;all&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;,&lt;span class="st"&gt;'sec2'&lt;/span&gt;, &lt;span class="st"&gt;'b'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;union&lt;/span&gt; &lt;span class="kw"&gt;all&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="st"&gt;'sec2'&lt;/span&gt;,&lt;span class="st"&gt;'c'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="kw"&gt;id&lt;/span&gt;, to_json(map_from_entries(collect_list(struct(sec, cont)))) &lt;span class="kw"&gt;as&lt;/span&gt; t&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;from&lt;/span&gt; tmp&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;a href="#cb3-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;group&lt;/span&gt; &lt;span class="kw"&gt;by&lt;/span&gt; &lt;span class="kw"&gt;id&lt;/span&gt;;&lt;/span&gt;
&lt;span id="cb3-10"&gt;&lt;a href="#cb3-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb3-11"&gt;&lt;a href="#cb3-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- +---+-----------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-12"&gt;&lt;a href="#cb3-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- |id |t                      |&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-13"&gt;&lt;a href="#cb3-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- +---+-----------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-14"&gt;&lt;a href="#cb3-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- |1  |{"sec1":"a","sec2":"b"}|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-15"&gt;&lt;a href="#cb3-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- |2  |{"sec2":"c"}           |&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-16"&gt;&lt;a href="#cb3-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- +---+-----------------------+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Add an element within the resulting object&lt;/strong&gt;, use
&lt;em&gt;concat_map&lt;/em&gt; to merge them. By using the coalesce function to
replace null with empty map, this avoids the collateral effect of nulls
that would result into null in any case (null + x = null)&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;tmp &lt;span class="kw"&gt;as&lt;/span&gt; (&lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;id&lt;/span&gt;,&lt;span class="st"&gt;'sec1'&lt;/span&gt; sec,&lt;span class="st"&gt;'a'&lt;/span&gt; cont&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;union&lt;/span&gt; &lt;span class="kw"&gt;all&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;,&lt;span class="st"&gt;'sec2'&lt;/span&gt;, &lt;span class="st"&gt;'b'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;union&lt;/span&gt; &lt;span class="kw"&gt;all&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-6"&gt;&lt;a href="#cb4-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="st"&gt;'sec2'&lt;/span&gt;,&lt;span class="st"&gt;'c'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-7"&gt;&lt;a href="#cb4-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="kw"&gt;id&lt;/span&gt;, to_json(&lt;/span&gt;
&lt;span id="cb4-8"&gt;&lt;a href="#cb4-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        concat_map(&lt;/span&gt;
&lt;span id="cb4-9"&gt;&lt;a href="#cb4-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="fu"&gt;coalesce&lt;/span&gt;(map(&lt;span class="ot"&gt;"id"&lt;/span&gt;,&lt;span class="kw"&gt;id&lt;/span&gt;),map()),&lt;/span&gt;
&lt;span id="cb4-10"&gt;&lt;a href="#cb4-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="fu"&gt;coalesce&lt;/span&gt;(map_from_entries(&lt;/span&gt;
&lt;span id="cb4-11"&gt;&lt;a href="#cb4-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                collect_list(&lt;/span&gt;
&lt;span id="cb4-12"&gt;&lt;a href="#cb4-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    struct(sec, cont))),map()))) &lt;span class="kw"&gt;as&lt;/span&gt; t&lt;/span&gt;
&lt;span id="cb4-13"&gt;&lt;a href="#cb4-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;from&lt;/span&gt; tmp&lt;/span&gt;
&lt;span id="cb4-14"&gt;&lt;a href="#cb4-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;group&lt;/span&gt; &lt;span class="kw"&gt;by&lt;/span&gt; &lt;span class="kw"&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-15"&gt;&lt;a href="#cb4-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-16"&gt;&lt;a href="#cb4-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- +---+---------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-17"&gt;&lt;a href="#cb4-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- |id |t                                |&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-18"&gt;&lt;a href="#cb4-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- +---+---------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-19"&gt;&lt;a href="#cb4-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- |1  |{"id":"1","sec1":"a","sec2":"b"}|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-20"&gt;&lt;a href="#cb4-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- |2  |{"id":"1","sec2":"c"}           |&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-21"&gt;&lt;a href="#cb4-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- +---+---------------------------------+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Create nested objects&lt;/strong&gt; and place them into one parent
object. The use of a named_struct allows to nest objects within a first
parent object:&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb5-1"&gt;&lt;a href="#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;secs &lt;span class="kw"&gt;as&lt;/span&gt; (&lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; p_id, &lt;span class="st"&gt;'sec1'&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; sec, &lt;span class="st"&gt;'hello'&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; cont&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;union&lt;/span&gt; &lt;span class="kw"&gt;all&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; p_id, &lt;span class="st"&gt;'sec2'&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; sec, &lt;span class="st"&gt;'world'&lt;/span&gt; cont),&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;tmp &lt;span class="kw"&gt;as&lt;/span&gt; (&lt;span class="kw"&gt;select&lt;/span&gt; p_id, map_from_entries(collect_list( struct(sec, cont) ) ) &lt;span class="kw"&gt;as&lt;/span&gt; t&lt;/span&gt;
&lt;span id="cb5-6"&gt;&lt;a href="#cb5-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;from&lt;/span&gt; secs&lt;/span&gt;
&lt;span id="cb5-7"&gt;&lt;a href="#cb5-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;group&lt;/span&gt; &lt;span class="kw"&gt;by&lt;/span&gt; p_id)&lt;/span&gt;
&lt;span id="cb5-8"&gt;&lt;a href="#cb5-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;select&lt;/span&gt; to_json( named_struct(&lt;span class="st"&gt;'id'&lt;/span&gt;, p_id, &lt;span class="st"&gt;'_childDocuments_'&lt;/span&gt;, collect_list(t))) &lt;span class="kw"&gt;as&lt;/span&gt; t&lt;/span&gt;
&lt;span id="cb5-9"&gt;&lt;a href="#cb5-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;from&lt;/span&gt; tmp&lt;/span&gt;
&lt;span id="cb5-10"&gt;&lt;a href="#cb5-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;group&lt;/span&gt; &lt;span class="kw"&gt;by&lt;/span&gt; p_id&lt;/span&gt;
&lt;span id="cb5-11"&gt;&lt;a href="#cb5-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-12"&gt;&lt;a href="#cb5-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- +-------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-13"&gt;&lt;a href="#cb5-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- |t                                                            |&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-14"&gt;&lt;a href="#cb5-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- +-------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-15"&gt;&lt;a href="#cb5-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- |{"id":1,"_childDocuments_":[{"sec1":"hello","sec2":"world"}]}|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-16"&gt;&lt;a href="#cb5-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- +-------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="good-practice-for-building-json-from-sql-within-spark"&gt;Good
practice for building json from SQL within spark&lt;/h2&gt;
&lt;p&gt;Since it is possible to create json elements and concatenate them
into objects with joins, it improves readibility to create each kind of
element step by step and at the end concatenate them into larger
objects. This should not degrade the performance thanks to the spark
lazy evaluation design.&lt;/p&gt;
&lt;p&gt;As a result, it is possible to begin with encounter information one
by one. Sections, then laboratories, medications and so on. Then it is
possible to build the encounter by combining all this stuff. Afterwards
comes the patient related informations. At the end, it is possible
include the encounters as nested childrens within the patients.&lt;/p&gt;
&lt;p&gt;By using this design it will be quite easy to enrich any element, or
moove some into other, repeat, rename, remove them. It will be also easy
to debug. The overall prototype would look like the below steps:&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb6-1"&gt;&lt;a href="#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- encounter labs step&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- encounter diags step&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- encounter sections step&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- patient step and nesting encounters into them&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-6"&gt;&lt;a href="#cb6-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- good point is: named_struct automatically removes empty fields&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-7"&gt;&lt;a href="#cb6-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-8"&gt;&lt;a href="#cb6-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;secs &lt;span class="kw"&gt;as&lt;/span&gt; (&lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; p_id, &lt;span class="st"&gt;'sec1'&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; sec, &lt;span class="st"&gt;'hello'&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; cont&lt;/span&gt;
&lt;span id="cb6-9"&gt;&lt;a href="#cb6-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;union&lt;/span&gt; &lt;span class="kw"&gt;all&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-10"&gt;&lt;a href="#cb6-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;select&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; p_id, &lt;span class="st"&gt;'sec2'&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; sec, &lt;span class="st"&gt;'world'&lt;/span&gt; cont),&lt;/span&gt;
&lt;span id="cb6-11"&gt;&lt;a href="#cb6-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;tmp &lt;span class="kw"&gt;as&lt;/span&gt; (&lt;span class="kw"&gt;select&lt;/span&gt; p_id, map_from_entries(collect_list( struct(sec, cont) ) ) &lt;span class="kw"&gt;as&lt;/span&gt; t&lt;/span&gt;
&lt;span id="cb6-12"&gt;&lt;a href="#cb6-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;from&lt;/span&gt; secs&lt;/span&gt;
&lt;span id="cb6-13"&gt;&lt;a href="#cb6-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;group&lt;/span&gt; &lt;span class="kw"&gt;by&lt;/span&gt; p_id)&lt;/span&gt;
&lt;span id="cb6-14"&gt;&lt;a href="#cb6-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;select&lt;/span&gt; to_json( named_struct(&lt;/span&gt;
&lt;span id="cb6-15"&gt;&lt;a href="#cb6-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;'id'&lt;/span&gt;, patient_id,&lt;/span&gt;
&lt;span id="cb6-16"&gt;&lt;a href="#cb6-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;'birthDate'&lt;/span&gt;, birthDate,&lt;/span&gt;
&lt;span id="cb6-17"&gt;&lt;a href="#cb6-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;'_childDocuments_'&lt;/span&gt;, collect_list(t)&lt;/span&gt;
&lt;span id="cb6-18"&gt;&lt;a href="#cb6-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb6-19"&gt;&lt;a href="#cb6-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ) &lt;span class="kw"&gt;as&lt;/span&gt; t&lt;/span&gt;
&lt;span id="cb6-20"&gt;&lt;a href="#cb6-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;from&lt;/span&gt; patients&lt;/span&gt;
&lt;span id="cb6-21"&gt;&lt;a href="#cb6-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;left&lt;/span&gt; &lt;span class="kw"&gt;join&lt;/span&gt; encounters &lt;span class="kw"&gt;using&lt;/span&gt; (patient_id)&lt;/span&gt;
&lt;span id="cb6-22"&gt;&lt;a href="#cb6-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;group&lt;/span&gt; &lt;span class="kw"&gt;by&lt;/span&gt; patient_id&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="limitations-of-spark-solr-lib"&gt;Limitations of spark-solr
lib&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;it does not support solr standalone (only solr-cloud)&lt;/li&gt;
&lt;li&gt;it does not handle multi-valued for childDocuemnt yet (fixed with a
patch)&lt;/li&gt;
&lt;li&gt;it does not handle two levels of childDocuments yet&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Mixing Spark and SolR — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/mixing-spark-and-solr" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/working-with-the-french-mesh</id>
    <title>What's the MESH</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2018-12-19&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;5 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="whats-the-mesh"&gt;What's the MESH&lt;/h1&gt;
&lt;h1 id="whats-the-french-mesh"&gt;What's the French MESH&lt;/h1&gt;
&lt;p&gt;This is basically a fat XML without documentation(?)&lt;/p&gt;
&lt;h1 id="what-is-the-data-structure"&gt;What is the data structure&lt;/h1&gt;
&lt;p&gt;The databricks spark-xml lib makes easy to transform an xml file into
a sparks dataframe.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode scala"&gt;&lt;code class="sourceCode scala"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; com&lt;span class="op"&gt;.&lt;/span&gt;databricks&lt;span class="op"&gt;.&lt;/span&gt;spark&lt;span class="op"&gt;.&lt;/span&gt;xml&lt;span class="op"&gt;.&lt;/span&gt;_&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;spark&lt;span class="op"&gt;.&lt;/span&gt;read&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;format&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"com.databricks.spark.xml"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;option&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"rowTag"&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"DescriptorRecord"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;load&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"fredesc2017.xml"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a href="#cb1-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;.&lt;/span&gt;persist&lt;/span&gt;
&lt;span id="cb1-7"&gt;&lt;a href="#cb1-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;registerTempTable&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"b"&lt;/span&gt;&lt;span class="op"&gt;).&lt;/span&gt;printSchema&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The resulting dataframe schema is quite complicated.&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode scala"&gt;&lt;code class="sourceCode scala"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;#root&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; AllowableQualifiersList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; AllowableQualifier&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Abbreviation&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; QualifierReferredTo&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; QualifierName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-8"&gt;&lt;a href="#cb2-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-9"&gt;&lt;a href="#cb2-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; QualifierUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-10"&gt;&lt;a href="#cb2-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;Annotation&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-11"&gt;&lt;a href="#cb2-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; ConceptList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-12"&gt;&lt;a href="#cb2-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Concept&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-13"&gt;&lt;a href="#cb2-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-14"&gt;&lt;a href="#cb2-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; CASN1Name&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-15"&gt;&lt;a href="#cb2-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; ConceptName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-16"&gt;&lt;a href="#cb2-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-17"&gt;&lt;a href="#cb2-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; ConceptRelationList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-18"&gt;&lt;a href="#cb2-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; ConceptRelation&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-19"&gt;&lt;a href="#cb2-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-20"&gt;&lt;a href="#cb2-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Concept1UI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-21"&gt;&lt;a href="#cb2-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Concept2UI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-22"&gt;&lt;a href="#cb2-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; _RelationName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-23"&gt;&lt;a href="#cb2-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; ConceptUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-24"&gt;&lt;a href="#cb2-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; RegistryNumber&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-25"&gt;&lt;a href="#cb2-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; RelatedRegistryNumberList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-26"&gt;&lt;a href="#cb2-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; RelatedRegistryNumber&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-27"&gt;&lt;a href="#cb2-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-28"&gt;&lt;a href="#cb2-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; ScopeNote&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-29"&gt;&lt;a href="#cb2-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; TermList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-30"&gt;&lt;a href="#cb2-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Term&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-31"&gt;&lt;a href="#cb2-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-32"&gt;&lt;a href="#cb2-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DateCreated&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-33"&gt;&lt;a href="#cb2-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Day&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-34"&gt;&lt;a href="#cb2-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Month&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-35"&gt;&lt;a href="#cb2-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Year&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-36"&gt;&lt;a href="#cb2-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; EntryVersion&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-37"&gt;&lt;a href="#cb2-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; SortVersion&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-38"&gt;&lt;a href="#cb2-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-39"&gt;&lt;a href="#cb2-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; TermNote&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-40"&gt;&lt;a href="#cb2-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; TermUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-41"&gt;&lt;a href="#cb2-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; ThesaurusIDlist&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-42"&gt;&lt;a href="#cb2-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; ThesaurusID&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-43"&gt;&lt;a href="#cb2-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-44"&gt;&lt;a href="#cb2-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; _ConceptPreferredTermYN&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-45"&gt;&lt;a href="#cb2-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; _IsPermutedTermYN&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-46"&gt;&lt;a href="#cb2-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; _LexicalTag&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-47"&gt;&lt;a href="#cb2-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; _RecordPreferredTermYN&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-48"&gt;&lt;a href="#cb2-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; TranslatorsScopeNote&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-49"&gt;&lt;a href="#cb2-49" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; _PreferredConceptYN&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-50"&gt;&lt;a href="#cb2-50" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; ConsiderAlso&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-51"&gt;&lt;a href="#cb2-51" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; DateCreated&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-52"&gt;&lt;a href="#cb2-52" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Day&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-53"&gt;&lt;a href="#cb2-53" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Month&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-54"&gt;&lt;a href="#cb2-54" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Year&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-55"&gt;&lt;a href="#cb2-55" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; DateEstablished&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-56"&gt;&lt;a href="#cb2-56" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Day&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-57"&gt;&lt;a href="#cb2-57" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Month&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-58"&gt;&lt;a href="#cb2-58" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Year&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-59"&gt;&lt;a href="#cb2-59" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; DateRevised&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-60"&gt;&lt;a href="#cb2-60" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Day&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-61"&gt;&lt;a href="#cb2-61" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Month&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-62"&gt;&lt;a href="#cb2-62" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; Year&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-63"&gt;&lt;a href="#cb2-63" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-64"&gt;&lt;a href="#cb2-64" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-65"&gt;&lt;a href="#cb2-65" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-66"&gt;&lt;a href="#cb2-66" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; EntryCombinationList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-67"&gt;&lt;a href="#cb2-67" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; EntryCombination&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-68"&gt;&lt;a href="#cb2-68" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-69"&gt;&lt;a href="#cb2-69" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; ECIN&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-70"&gt;&lt;a href="#cb2-70" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorReferredTo&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-71"&gt;&lt;a href="#cb2-71" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-72"&gt;&lt;a href="#cb2-72" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-73"&gt;&lt;a href="#cb2-73" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-74"&gt;&lt;a href="#cb2-74" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; QualifierReferredTo&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-75"&gt;&lt;a href="#cb2-75" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; QualifierName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-76"&gt;&lt;a href="#cb2-76" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-77"&gt;&lt;a href="#cb2-77" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; QualifierUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-78"&gt;&lt;a href="#cb2-78" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; ECOUT&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-79"&gt;&lt;a href="#cb2-79" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorReferredTo&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-80"&gt;&lt;a href="#cb2-80" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-81"&gt;&lt;a href="#cb2-81" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-82"&gt;&lt;a href="#cb2-82" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-83"&gt;&lt;a href="#cb2-83" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; QualifierReferredTo&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-84"&gt;&lt;a href="#cb2-84" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; QualifierName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-85"&gt;&lt;a href="#cb2-85" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-86"&gt;&lt;a href="#cb2-86" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; QualifierUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-87"&gt;&lt;a href="#cb2-87" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; HistoryNote&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-88"&gt;&lt;a href="#cb2-88" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; NLMClassificationNumber&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-89"&gt;&lt;a href="#cb2-89" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; OnlineNote&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-90"&gt;&lt;a href="#cb2-90" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; PharmacologicalActionList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-91"&gt;&lt;a href="#cb2-91" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; PharmacologicalAction&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-92"&gt;&lt;a href="#cb2-92" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-93"&gt;&lt;a href="#cb2-93" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorReferredTo&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-94"&gt;&lt;a href="#cb2-94" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-95"&gt;&lt;a href="#cb2-95" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-96"&gt;&lt;a href="#cb2-96" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-97"&gt;&lt;a href="#cb2-97" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; PreviousIndexingList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-98"&gt;&lt;a href="#cb2-98" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; PreviousIndexing&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-99"&gt;&lt;a href="#cb2-99" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-100"&gt;&lt;a href="#cb2-100" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; PublicMeSHNote&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-101"&gt;&lt;a href="#cb2-101" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; SeeRelatedList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-102"&gt;&lt;a href="#cb2-102" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; SeeRelatedDescriptor&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-103"&gt;&lt;a href="#cb2-103" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-104"&gt;&lt;a href="#cb2-104" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorReferredTo&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-105"&gt;&lt;a href="#cb2-105" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorName&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-106"&gt;&lt;a href="#cb2-106" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; &lt;span class="ex"&gt;String&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-107"&gt;&lt;a href="#cb2-107" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; DescriptorUI&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-108"&gt;&lt;a href="#cb2-108" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; TreeNumberList&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-109"&gt;&lt;a href="#cb2-109" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; TreeNumber&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;array&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-110"&gt;&lt;a href="#cb2-110" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|&lt;/span&gt;    &lt;span class="op"&gt;|--&lt;/span&gt; element&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;string&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;containsNull &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-111"&gt;&lt;a href="#cb2-111" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;# &lt;span class="op"&gt;|--&lt;/span&gt; _DescriptorClass&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;nullable &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The folowing code extracts the first element of the term list. There
is 54 one of them in the 2017 mesh version. It is possible to get all of
them by union.&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;sql&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"""with&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;tmp &lt;span class="fu"&gt;as&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;select&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  treenumberlist&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;TreeNumber&lt;/span&gt; as tree&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  descriptorui as descriptor&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;explode&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;conceptlist&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;concept&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;termlist&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;term&lt;/span&gt;&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="op"&gt;])&lt;/span&gt; as t&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  from b&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;select tree&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  descriptor&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;a href="#cb3-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  t&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;string&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-10"&gt;&lt;a href="#cb3-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  t&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;termui&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-11"&gt;&lt;a href="#cb3-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  t&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;_ConceptPreferredTermYN&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-12"&gt;&lt;a href="#cb3-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;explode&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;t&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;thesaurusidlist&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;thesaurusid&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt; as dict&lt;/span&gt;
&lt;span id="cb3-13"&gt;&lt;a href="#cb3-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;from tmp&lt;span class="st"&gt;""")&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-14"&gt;&lt;a href="#cb3-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;show&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dv"&gt;30&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-15"&gt;&lt;a href="#cb3-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// +--------------------+----------+--------------------+----------+-----------------------+----------------+&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-16"&gt;&lt;a href="#cb3-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |                tree|descriptor|              string|    termui|_ConceptPreferredTermYN|            dict|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-17"&gt;&lt;a href="#cb3-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// +--------------------+----------+--------------------+----------+-----------------------+----------------+&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-18"&gt;&lt;a href="#cb3-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[D03.633.100.221....|   D000001|          Calcimycin|   T000002|                      Y|  FDA SRS (2014)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-19"&gt;&lt;a href="#cb3-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[D03.633.100.221....|   D000001|          Calcimycin|   T000002|                      Y|      NLM (1975)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-20"&gt;&lt;a href="#cb3-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[D02.705.400.625....|   D000002|             Temefos|   T000008|                      Y|  FDA SRS (2014)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-21"&gt;&lt;a href="#cb3-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[D02.705.400.625....|   D000002|             Temefos|   T000008|                      Y|      INN (19XX)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-22"&gt;&lt;a href="#cb3-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[D02.705.400.625....|   D000002|             Temefos|   T000008|                      Y|     USAN (1974)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-23"&gt;&lt;a href="#cb3-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[D02.705.400.625....|   D000002|            Temephos|   T000007|                      N|      NLM (1996)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-24"&gt;&lt;a href="#cb3-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[J01.576.423.200....|   D000003|           Abattoirs|   T000009|                      Y|      NLM (1966)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-25"&gt;&lt;a href="#cb3-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[J01.576.423.200....|   D000003|    Slaughter Houses|T000901742|                      N|      NLM (2017)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-26"&gt;&lt;a href="#cb3-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[J01.576.423.200....|   D000003|     Slaughter House|T000901743|                      N|      NLM (2017)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-27"&gt;&lt;a href="#cb3-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[J01.576.423.200....|   D000003|     Slaughterhouses|   T000010|                      N|      UNK (19XX)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-28"&gt;&lt;a href="#cb3-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[L01.143.506.598....|   D000004|Abbreviations as ...|   T698652|                      Y|      NLM (2008)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-29"&gt;&lt;a href="#cb3-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |       [A01.923.047]|   D000005|             Abdomen|   T000012|                      Y|      NLM (1966)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-30"&gt;&lt;a href="#cb3-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[C10.597.617.044....|   D000006|      Abdomen, Acute|   T000013|                      Y|      NLM (1966)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-31"&gt;&lt;a href="#cb3-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[C10.597.617.044....|   D000006| Abdomen chirurgical|fre0138059|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-32"&gt;&lt;a href="#cb3-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[C10.597.617.044....|   D000006|      Abdomen urgent|fre0138060|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-33"&gt;&lt;a href="#cb3-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007|  Abdominal Injuries|   T000015|                      Y|      NLM (1966)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-34"&gt;&lt;a href="#cb3-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007| Injuries, Abdominal|   T000014|                      N|      UNK (19XX)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-35"&gt;&lt;a href="#cb3-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007|Traumatismes de l...|fre0037777|                      Y|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-36"&gt;&lt;a href="#cb3-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007|Blessures abdomin...|fre0072220|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-37"&gt;&lt;a href="#cb3-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007|Blessures de l'ab...|fre0103940|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-38"&gt;&lt;a href="#cb3-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007| Lésions abdominales|fre0113338|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-39"&gt;&lt;a href="#cb3-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007|Lésions de l'abdomen|fre0113337|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-40"&gt;&lt;a href="#cb3-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007|Lésions traumatiq...|fre0103942|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-41"&gt;&lt;a href="#cb3-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007|Lésions traumatiq...|fre0103941|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-42"&gt;&lt;a href="#cb3-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |           [C26.017]|   D000007|Traumatismes abdo...|fre0047606|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-43"&gt;&lt;a href="#cb3-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |       [C04.588.033]|   D000008| Abdominal Neoplasms|   T000016|                      Y|      NLM (1966)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-44"&gt;&lt;a href="#cb3-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |   [A02.633.567.050]|   D000009|   Abdominal Muscles|   T000018|                      Y|      NLM (1966)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-45"&gt;&lt;a href="#cb3-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |   [A02.633.567.050]|   D000009|    Muscle abdominal|fre0042987|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-46"&gt;&lt;a href="#cb3-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |   [A02.633.567.050]|   D000009|Muscles de l'abdomen|fre0042988|                      N|French thesaurus|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-47"&gt;&lt;a href="#cb3-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// |[A08.800.800.120....|   D000010|      Abducens Nerve|   T000019|                      Y|      NLM (1966)|&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-48"&gt;&lt;a href="#cb3-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// +--------------------+----------+--------------------+----------+-----------------------+----------------+&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-49"&gt;&lt;a href="#cb3-49" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// only showing top 30 rows&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=What's the MESH — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/working-with-the-french-mesh" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/solr-joins-thought-spark</id>
    <title>Solr joins thought Spark</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2019-01-13&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;2 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="solr-joins-thought-spark"&gt;Solr joins thought Spark&lt;/h1&gt;
&lt;h2 id="context"&gt;Context&lt;/h2&gt;
&lt;p&gt;SolR is great to search within complexes documents. However it is
weak to make complexes joins between documents and lack for expressive
languages. Combining both solr and spark let envisage having best of two
worlds.&lt;/p&gt;
&lt;h3 id="dataset"&gt;Dataset&lt;/h3&gt;
&lt;table style="width:33%;"&gt;
&lt;colgroup&gt;
&lt;col style="width: 18%"&gt;
&lt;col style="width: 15%"&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;patient_id&lt;/td&gt;
&lt;td&gt;visit_id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="r1"&gt;R1&lt;/h3&gt;
&lt;table style="width:33%;"&gt;
&lt;colgroup&gt;
&lt;col style="width: 18%"&gt;
&lt;col style="width: 15%"&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;patient_id&lt;/td&gt;
&lt;td&gt;visit_id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="r2"&gt;R2&lt;/h3&gt;
&lt;table style="width:33%;"&gt;
&lt;colgroup&gt;
&lt;col style="width: 18%"&gt;
&lt;col style="width: 15%"&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;patient_id&lt;/td&gt;
&lt;td&gt;visit_id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="use-case-q1-and-q2"&gt;Use case: Q1 AND Q2&lt;/h2&gt;
&lt;p&gt;Let's say you have defined two queries Q1 and Q2 which have
respectively R1 and R2. Now you d'like to know which patients have both
kind of visits.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; R1.patient_id, R1.visit_id&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; R1&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;JOIN&lt;/span&gt; R2 &lt;span class="kw"&gt;USING&lt;/span&gt; (patient_id)&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;AND&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;R2.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; R1.visit_id&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="use-case-q1-or-q2"&gt;Use Case: Q1 OR Q2&lt;/h2&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; patient_id, visit_id &lt;span class="kw"&gt;FROM&lt;/span&gt; R1)&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;UNION&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; patient_id, visit_id &lt;span class="kw"&gt;FROM&lt;/span&gt; R2)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="use-case-q1-and-not-q2"&gt;Use Case: Q1 AND NOT Q2&lt;/h2&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; patient_id, visit_id &lt;span class="kw"&gt;FROM&lt;/span&gt; R1)&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;MINUS&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; patient_id, visit_id &lt;span class="kw"&gt;FROM&lt;/span&gt; R2)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="use-case-q1-then-q2"&gt;Use Case: Q1 THEN Q2&lt;/h2&gt;
&lt;p&gt;Say we also have date along with data.&lt;/p&gt;
&lt;p&gt;Say you want all Patients who had Q2 &amp;gt;1&amp;gt; Q1. You need to have
the dates.&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;SELECT&lt;/span&gt; R1.patient_id, R1.visit_id, R1.&lt;span class="dt"&gt;date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;FROM&lt;/span&gt; R1&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;JOIN&lt;/span&gt; R2 &lt;span class="kw"&gt;USING&lt;/span&gt; (patient_id)&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;AND&lt;/span&gt; R2.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; R1.visit_id&lt;/span&gt;
&lt;span id="cb4-6"&gt;&lt;a href="#cb4-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;AND&lt;/span&gt; R2.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R1.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="operations"&gt;Operations&lt;/h2&gt;
&lt;p&gt;Given this formula: &lt;strong&gt;(Q1 AND Q2) &amp;lt;2&amp;lt; Q3&lt;/strong&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb5-1"&gt;&lt;a href="#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WITH&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;1&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-6"&gt;&lt;a href="#cb5-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;4&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb5-7"&gt;&lt;a href="#cb5-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q2 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-8"&gt;&lt;a href="#cb5-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-9"&gt;&lt;a href="#cb5-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;4&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb5-10"&gt;&lt;a href="#cb5-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q3 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;5&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-11"&gt;&lt;a href="#cb5-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-12"&gt;&lt;a href="#cb5-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;6&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb5-13"&gt;&lt;a href="#cb5-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q1.patient_id&lt;/span&gt;
&lt;span id="cb5-14"&gt;&lt;a href="#cb5-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q1&lt;/span&gt;
&lt;span id="cb5-15"&gt;&lt;a href="#cb5-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;JOIN&lt;/span&gt; Q2 &lt;span class="kw"&gt;USING&lt;/span&gt;(patient_id)&lt;/span&gt;
&lt;span id="cb5-16"&gt;&lt;a href="#cb5-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-17"&gt;&lt;a href="#cb5-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q2.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; Q1.visit_id),&lt;/span&gt;
&lt;span id="cb5-18"&gt;&lt;a href="#cb5-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T2 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q1.patient_id&lt;/span&gt;
&lt;span id="cb5-19"&gt;&lt;a href="#cb5-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q1&lt;/span&gt;
&lt;span id="cb5-20"&gt;&lt;a href="#cb5-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;JOIN&lt;/span&gt; Q3 &lt;span class="kw"&gt;USING&lt;/span&gt;(patient_id)&lt;/span&gt;
&lt;span id="cb5-21"&gt;&lt;a href="#cb5-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-22"&gt;&lt;a href="#cb5-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q3.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; Q1.visit_id&lt;/span&gt;
&lt;span id="cb5-23"&gt;&lt;a href="#cb5-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q3.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; Q1.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb5-24"&gt;&lt;a href="#cb5-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T3 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q2.patient_id&lt;/span&gt;
&lt;span id="cb5-25"&gt;&lt;a href="#cb5-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q2&lt;/span&gt;
&lt;span id="cb5-26"&gt;&lt;a href="#cb5-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;JOIN&lt;/span&gt; Q3 &lt;span class="kw"&gt;USING&lt;/span&gt;(patient_id)&lt;/span&gt;
&lt;span id="cb5-27"&gt;&lt;a href="#cb5-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-28"&gt;&lt;a href="#cb5-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q3.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; Q2.visit_id&lt;/span&gt;
&lt;span id="cb5-29"&gt;&lt;a href="#cb5-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q3.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; Q2.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb5-30"&gt;&lt;a href="#cb5-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T1)&lt;/span&gt;
&lt;span id="cb5-31"&gt;&lt;a href="#cb5-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INTERSECT&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-32"&gt;&lt;a href="#cb5-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T2)&lt;/span&gt;
&lt;span id="cb5-33"&gt;&lt;a href="#cb5-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INTERSECT&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-34"&gt;&lt;a href="#cb5-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T2)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Given this formula: &lt;strong&gt;(Q1 OR Q2) AND Q3&lt;/strong&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb6-1"&gt;&lt;a href="#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WITH&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;1&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-6"&gt;&lt;a href="#cb6-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;4&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb6-7"&gt;&lt;a href="#cb6-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q2 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-8"&gt;&lt;a href="#cb6-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-9"&gt;&lt;a href="#cb6-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;4&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb6-10"&gt;&lt;a href="#cb6-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q3 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;5&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-11"&gt;&lt;a href="#cb6-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;UNION&lt;/span&gt; &lt;span class="kw"&gt;ALL&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-12"&gt;&lt;a href="#cb6-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;6&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb6-13"&gt;&lt;a href="#cb6-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q1.patient_id&lt;/span&gt;
&lt;span id="cb6-14"&gt;&lt;a href="#cb6-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q1&lt;/span&gt;
&lt;span id="cb6-15"&gt;&lt;a href="#cb6-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;UNION&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-16"&gt;&lt;a href="#cb6-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;SELECT&lt;/span&gt; Q2.patient_id&lt;/span&gt;
&lt;span id="cb6-17"&gt;&lt;a href="#cb6-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q2),&lt;/span&gt;
&lt;span id="cb6-18"&gt;&lt;a href="#cb6-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T2 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q3.patient_id&lt;/span&gt;
&lt;span id="cb6-19"&gt;&lt;a href="#cb6-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q3)&lt;/span&gt;
&lt;span id="cb6-20"&gt;&lt;a href="#cb6-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T1)&lt;/span&gt;
&lt;span id="cb6-21"&gt;&lt;a href="#cb6-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INTERSECT&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-22"&gt;&lt;a href="#cb6-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T2)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Given this formula: &lt;strong&gt;Q1 AND Q2 AND Q3&lt;/strong&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb7-1"&gt;&lt;a href="#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WITH&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id),&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q2 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id),&lt;/span&gt;
&lt;span id="cb7-4"&gt;&lt;a href="#cb7-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q3 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id),&lt;/span&gt;
&lt;span id="cb7-5"&gt;&lt;a href="#cb7-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q1.patient_id&lt;/span&gt;
&lt;span id="cb7-6"&gt;&lt;a href="#cb7-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q1&lt;/span&gt;
&lt;span id="cb7-7"&gt;&lt;a href="#cb7-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;JOIN&lt;/span&gt; Q2 &lt;span class="kw"&gt;USING&lt;/span&gt;(patient_id)&lt;/span&gt;
&lt;span id="cb7-8"&gt;&lt;a href="#cb7-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-9"&gt;&lt;a href="#cb7-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q2.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; Q1.visit_id),&lt;/span&gt;
&lt;span id="cb7-10"&gt;&lt;a href="#cb7-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T2 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q2.patient_id&lt;/span&gt;
&lt;span id="cb7-11"&gt;&lt;a href="#cb7-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q2&lt;/span&gt;
&lt;span id="cb7-12"&gt;&lt;a href="#cb7-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;JOIN&lt;/span&gt; Q3 &lt;span class="kw"&gt;USING&lt;/span&gt;(patient_id)&lt;/span&gt;
&lt;span id="cb7-13"&gt;&lt;a href="#cb7-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-14"&gt;&lt;a href="#cb7-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q3.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; Q2.visit_id),&lt;/span&gt;
&lt;span id="cb7-15"&gt;&lt;a href="#cb7-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T3 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q1.patient_id&lt;/span&gt;
&lt;span id="cb7-16"&gt;&lt;a href="#cb7-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q1&lt;/span&gt;
&lt;span id="cb7-17"&gt;&lt;a href="#cb7-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;JOIN&lt;/span&gt; Q3 &lt;span class="kw"&gt;USING&lt;/span&gt;(patient_id)&lt;/span&gt;
&lt;span id="cb7-18"&gt;&lt;a href="#cb7-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-19"&gt;&lt;a href="#cb7-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q3.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; Q1.visit_id)&lt;/span&gt;
&lt;span id="cb7-20"&gt;&lt;a href="#cb7-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T1)&lt;/span&gt;
&lt;span id="cb7-21"&gt;&lt;a href="#cb7-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INTERSECT&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-22"&gt;&lt;a href="#cb7-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T2)&lt;/span&gt;
&lt;span id="cb7-23"&gt;&lt;a href="#cb7-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INTERSECT&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-24"&gt;&lt;a href="#cb7-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T3)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Given this formula: &lt;strong&gt;Q1 &amp;lt;1&amp;lt; Q2 &amp;lt;1&amp;lt; Q3&lt;/strong&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb8-1"&gt;&lt;a href="#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WITH&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q2 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;4&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q3 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;5&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q1.patient_id&lt;/span&gt;
&lt;span id="cb8-6"&gt;&lt;a href="#cb8-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q1&lt;/span&gt;
&lt;span id="cb8-7"&gt;&lt;a href="#cb8-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;JOIN&lt;/span&gt; Q2 &lt;span class="kw"&gt;USING&lt;/span&gt;(patient_id)&lt;/span&gt;
&lt;span id="cb8-8"&gt;&lt;a href="#cb8-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-9"&gt;&lt;a href="#cb8-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q2.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; Q1.visit_id&lt;/span&gt;
&lt;span id="cb8-10"&gt;&lt;a href="#cb8-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q2.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;&amp;gt;=&lt;/span&gt; Q1.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb8-11"&gt;&lt;a href="#cb8-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T2 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q2.patient_id&lt;/span&gt;
&lt;span id="cb8-12"&gt;&lt;a href="#cb8-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q2&lt;/span&gt;
&lt;span id="cb8-13"&gt;&lt;a href="#cb8-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;JOIN&lt;/span&gt; Q3 &lt;span class="kw"&gt;USING&lt;/span&gt;(patient_id)&lt;/span&gt;
&lt;span id="cb8-14"&gt;&lt;a href="#cb8-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-15"&gt;&lt;a href="#cb8-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q3.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; Q2.visit_id&lt;/span&gt;
&lt;span id="cb8-16"&gt;&lt;a href="#cb8-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q3.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;&amp;gt;=&lt;/span&gt; Q2.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-17"&gt;&lt;a href="#cb8-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T1)&lt;/span&gt;
&lt;span id="cb8-18"&gt;&lt;a href="#cb8-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;INTERSECT&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-19"&gt;&lt;a href="#cb8-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T2)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Given this formula: &lt;strong&gt;Q1 &amp;lt;1&amp;lt; Q2 AND NOT Q3&lt;/strong&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode sql"&gt;&lt;code class="sourceCode sql"&gt;&lt;span id="cb9-1"&gt;&lt;a href="#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;WITH&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="#cb9-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb9-3"&gt;&lt;a href="#cb9-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q2 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;4&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb9-4"&gt;&lt;a href="#cb9-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Q3 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; patient_id, &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; visit_id, &lt;span class="dv"&gt;5&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;date&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb9-5"&gt;&lt;a href="#cb9-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T1 &lt;span class="kw"&gt;as&lt;/span&gt;  (&lt;span class="kw"&gt;SELECT&lt;/span&gt; Q1.patient_id&lt;/span&gt;
&lt;span id="cb9-6"&gt;&lt;a href="#cb9-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;FROM&lt;/span&gt; Q1&lt;/span&gt;
&lt;span id="cb9-7"&gt;&lt;a href="#cb9-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;JOIN&lt;/span&gt; Q2 &lt;span class="kw"&gt;USING&lt;/span&gt;(patient_id)&lt;/span&gt;
&lt;span id="cb9-8"&gt;&lt;a href="#cb9-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;WHERE&lt;/span&gt; &lt;span class="kw"&gt;TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-9"&gt;&lt;a href="#cb9-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q2.visit_id &lt;span class="op"&gt;!=&lt;/span&gt; Q1.visit_id&lt;/span&gt;
&lt;span id="cb9-10"&gt;&lt;a href="#cb9-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;AND&lt;/span&gt; Q2.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;&amp;gt;=&lt;/span&gt; Q1.&lt;span class="dt"&gt;date&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb9-11"&gt;&lt;a href="#cb9-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; T1)&lt;/span&gt;
&lt;span id="cb9-12"&gt;&lt;a href="#cb9-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;MINUS&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-13"&gt;&lt;a href="#cb9-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="kw"&gt;SELECT&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="kw"&gt;FROM&lt;/span&gt; Q3)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="isolating-matching-records"&gt;Isolating matching records&lt;/h2&gt;
&lt;p&gt;For each Qn it would be interesting to get the matching visit. This
allows to run the solr queries afterwards.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Solr joins thought Spark — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/solr-joins-thought-spark" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/earth-sana-in-corpore-sano</id>
    <title>Earth sana in corpore sano</title>
    <updated>2021-11-07T15:49:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2019-03-31&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="earth-sana-in-corpore-sano"&gt;Earth sana in corpore sano&lt;/h1&gt;
&lt;h2 id="society-produces-more-and-more-energy"&gt;Society produces more and
more Energy&lt;/h2&gt;
&lt;p&gt;Human have gradualy been less and less physical: hunter/trapper,
farmer, workers and novadays digitalized works. In the meantime, it
turns out food has been more and more easy to get. We saturate of
energy.&lt;/p&gt;
&lt;p&gt;While sport is a fairly ealthy activity, the lost of energy is a
pity. Worst, going to the gym room does not collect that energy but in
addition needs energy to make those sport machine active. This man-power
could be use for other purposes.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/gym.webp" class="align-center" style="width:75.0%" alt="Energy"&gt;&lt;/p&gt;
&lt;h2 id="society-produces-more-and-more-waste"&gt;Society produces more and
more Waste&lt;/h2&gt;
&lt;p&gt;Waste appeared in the begining of 20th century. Before that, most of
human production were reused: from animal bones and skin to human feces.
However novodays, the waste is far from being a profitable industry.&lt;/p&gt;
&lt;p&gt;We all are aware that industry produces way too much plastic
packaging. While most people pay attention to put thoses wastes into
trash, some do not. The reasons of this lack of care of packaging is
unknown and might be related to education, mood or loss of attention.
However what is clearly identified is the reason why industry uses such
amount of packaging: this ease customers experience.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/coca.webp" class="align-center" style="width:75.0%" alt="Packaging"&gt;&lt;/p&gt;
&lt;h2 id="eco-sport-best-of-two-worlds"&gt;Eco-Sport: Best of Two Worlds&lt;/h2&gt;
&lt;p&gt;Let's say every jogger would gather every waste he finds in a plastic
bag. This would make it's practice way more fun, and also it's energy
would be used efficiently. In addition let's say people would see that
jogger gather those things, I bet a few proportion (children in
particular) would adopt this practice. Worst case, they would not be so
prone to leave rubbish liying anymore !&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/eco-sport.webp" class="align-center" style="width:75.0%" alt="Echo Sport"&gt;&lt;/p&gt;
&lt;p&gt;There is so many healthy sports to practice in town, forest, sea,
river and so on and each might be turned in eco-sport! I have right now
no idea what eco-friendly gesture a boxer might have...&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/eco-boxe.webp" class="align-center" style="width:75.0%" alt="Echo Boxe"&gt;&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Earth sana in corpore sano — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-11-07 15:49&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/earth-sana-in-corpore-sano" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/going-barefoot</id>
    <title>Going Barefoot</title>
    <updated>2021-08-20T15:30:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2019-04-07&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="going-barefoot"&gt;Going Barefoot&lt;/h1&gt;
&lt;h2 id="every-body-has-unbalanced-legs"&gt;Every body has unbalanced
legs&lt;/h2&gt;
&lt;p&gt;Humans are not symetric. As a result the legs are not exactly the
same size. For some the size diffence leads to pathologies particularly
for sportsmen. Thurty percent of running people have the iliotibial band
syndrome which is a consequence of such unbalenced body. As a chronic
disease it is complicated to heal and sometimes changing shoes or
environment is sufficient to relapse and a podiastrist treatment is
often necessary.&lt;/p&gt;
&lt;h2 id="podiastrists-advice-orthopaedic-insoles"&gt;Podiastrists advice
orthopaedic insoles&lt;/h2&gt;
&lt;p&gt;Most of them will sell to you their insoles in order to rebalance
your posture properly. Insoles have multiple drawbacks: - they costs a
lot, are not reimbursed, and need to be replaced every year - they imply
a dependency to your podiastrist - your body will adapt to the insole,
and it is discuradged to walk without&lt;/p&gt;
&lt;h2 id="the-minimal-shoes-awareness"&gt;The minimal shoes awareness&lt;/h2&gt;
&lt;p&gt;Being overly dependant of a piece of cardboard was innapropriate to
me. Since almost every body is asymetric and almost 30% of runner are
using insoles, how did humans were hunting in the 200 million past years
without our highly skilled podiastrists, and even without shoes ? Am I
an not supposed to travel by myself ? The minimal shoes were an elegant
solution to all that doubt.&lt;/p&gt;
&lt;h2 id="walking-with-minimal-shoes"&gt;Walking with minimal shoes&lt;/h2&gt;
&lt;p&gt;I bought a pair of minimal shoes, and tried to walk as usual, but
lighter on my feets. Sadly this has not improved a lot my condition an
my knee pain. After a while I realized this was not the right way of
doing. When walking barefoot I was naturally walking with forefoot
before. I have been walking this way for about 2 weeks, and my knee is
far better. Also I can feel my muscle adapting: I am much more using my
calves, and my foot toes and so on. This muscle reinforcement will be
needed when I will be able to run this way soon.&lt;/p&gt;
&lt;h2 id="running-with-minimal-shoes"&gt;Running with minimal shoes&lt;/h2&gt;
&lt;p&gt;While walking forefoot is far from obvious, running with minimal
shoes does not allow other attitude. I have tested multiple series of
few distance and I felt the tendons of my feets not ready to support
more distance right now. Also the Achylles tendons is very requested
that way.&lt;/p&gt;
&lt;h2 id="conclusion-after-two-month"&gt;Conclusion after two month&lt;/h2&gt;
&lt;p&gt;My iliac band syndrome looks far better. Even after walking hours, I
do not feel pain by night in the knee. I fell my feets being more and
more robusts, and my body balance more stable. I am thinking this
transition would be useful for people with back of hip pain too.&lt;/p&gt;
&lt;p&gt;Better than having orthopeadic insoles, walking barefoot is possible
and advised. The physiologic changes are huge and the transition must be
slow.&lt;/p&gt;
&lt;p&gt;There is no possible concession with using minimal shoes: there is no
return. It's over with regular shoes.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Going Barefoot — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-20 15:30&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/going-barefoot" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/importance-of-teaching</id>
    <title>Importance of Teaching</title>
    <updated>2021-11-07T15:49:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2019-07-07&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="importance-of-teaching"&gt;Importance of Teaching&lt;/h1&gt;
&lt;p&gt;Today knowledge &lt;strong&gt;exists&lt;/strong&gt;. Search-engine and
recomendation-algorithms makes knowledge &lt;strong&gt;accessible&lt;/strong&gt;. We
live in a knowledge &lt;strong&gt;opulence&lt;/strong&gt;. Does this mean we make a
good use of the knowledge ?&lt;/p&gt;
&lt;h1 id="opulence-is-counter-productive"&gt;Opulence is counter
productive&lt;/h1&gt;
&lt;p&gt;&lt;img src="/images/fish.webp" alt="image"&gt;&lt;/p&gt;
&lt;p&gt;For multiple reason among reducing consumption from predatory, fish
use &lt;strong&gt;schooling&lt;/strong&gt;: they regroup and swim in the same
direction. An interpretation is that the predator is less able to make
choice in this context of opulence.&lt;/p&gt;
&lt;p&gt;Paradoxally, living in a megalopole usually increase lonely and
people decrease their activity. Opulence of offer limit the usage.&lt;/p&gt;
&lt;p&gt;I am pretty sure the opulence of information on the web acts in the
same manner. The potential is huge, but the usage is low.&lt;/p&gt;
&lt;h1 id="faster-but-less-emotion"&gt;Faster, but less emotion&lt;/h1&gt;
&lt;p&gt;Before internet, knowledge was physically shared among people or
books. The knowledge came together with an emotional context. Some
memory method use emotion to ehnance performances.&lt;/p&gt;
&lt;p&gt;Internet knowledge does not provide such emotion together with the
information. Therefore, the memory processus cannot be enhanced
naturally. The is a need to reinforce the internet knowledges.&lt;/p&gt;
&lt;h1 id="teaching"&gt;Teaching&lt;/h1&gt;
&lt;p&gt;There is multiple ways of teaching: explaining to others, writing a
blog-post, self explaining by mind. In every cases, teaching need a
synthesis step, and structure the informations to improve understanding
and finally ease the learning.&lt;/p&gt;
&lt;p&gt;Teaching is a powerful way of consolidating the knowledges. It helps
to raise error or superficial understanding. It has interesting
advantages: the teaching materials can be used to re-activate
knowledges, and also reduce the cognitive load.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In the days of knowledge opulence, there is a numeric hygiene to fix
the informations and take advantage of it.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Importance of Teaching — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-11-07 15:49&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/importance-of-teaching" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/benefits-of-functional-linux-distro</id>
    <title>Benefits of functional
linux distro</title>
    <updated>2020-06-06T22:05:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2019-08-17&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="benefits-of-functional-linux-distro"&gt;Benefits of functional
linux distro&lt;/h1&gt;
&lt;p&gt;Operating System is a tool to build and create other tools. OS is
secondary and the perfect one should be less present as possible. Less
time fighting with installation, less time with configuration, less time
with frustration.&lt;/p&gt;
&lt;p&gt;My first contact with linux has been ubuntu, and I am still using it
at work: using a mainstream tool, is a security and the promize to find
out solution fast on forum, blogs. When comes new version of ubuntu LTS,
this is a pain to migrate, and always a lost of energy so it is usual to
be frustrated and keeping and old OS with old software dependency.&lt;/p&gt;
&lt;p&gt;Then I gave a try to rolling-release distribution: Archlinux. The
good point is you never late and get the latest version on anything.
However I felt that OS was taking more and more importance in my daily
practice ; any package upgrade was a critical action. I finally become
very quiet with upgrade, and paradoxally late again with software
release.&lt;/p&gt;
&lt;p&gt;By chance I recently discovered functional programming in general,
and functional OS in particular. Nixos and Guix are both exploiting the
idea of immutability to build a very robust OS design. This allows to
rollback any bad situation very easily. The cost of this power is to
learn how to master the beast: haskell or scheme programming language
respectively. An I d'say that's an opportunity to learn new languages of
interest.&lt;/p&gt;
&lt;p&gt;While guix is more appealing for its full-GNU support I choosed
nixos. The reason is the packet manager called nix can be installed and
used on any distribution. Therefore I can take my time to learn haskell
and keep ubuntu as a security for daily primary objective: having a
transparent and robust OS.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Benefits of functional
linux distro — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2020-06-06 22:05&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/benefits-of-functional-linux-distro" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/easy-neovim-with-nix</id>
    <title>Easy neovim with nix</title>
    <updated>2020-06-06T22:05:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2019-08-22&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="easy-neovim-with-nix"&gt;Easy neovim with nix&lt;/h1&gt;
&lt;p&gt;In this post, I will show how to maintain a neovim configuration with
the &lt;strong&gt;nix&lt;/strong&gt; package manager. Nix can be installed on any
linux distribution with a single sudo bash script.&lt;/p&gt;
&lt;p&gt;One of the good point is it ease the way to install and configure
softwares: below is an example on how to install neomutt and several vim
packages. In case a package does not yet exists or is not up-to-date,
the nixpkgs github repository is the place to make pull requests.&lt;/p&gt;
&lt;p&gt;In case the merge is accepted, the nix unstable channel will get the
modification few hours later, and any body is able to install the
package.&lt;/p&gt;
&lt;p&gt;Nix is well documented and the community looks extraordinary active.
However the syntax and what happens behind the scene is for now a source
of curiosity for me: I have not yet switch to &lt;strong&gt;nixos&lt;/strong&gt;,
and only be using the nix manager on few servers.&lt;/p&gt;
&lt;p&gt;Still some packages are bogus, but things looks moving fast and I
such active community makes the invest confident.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="pp"&gt;# .config/nixpkgs/config.nix&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;{&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  packageOverrides &lt;span class="ot"&gt;=&lt;/span&gt; pkgs&lt;span class="op"&gt;:&lt;/span&gt; with pkgs; rec {&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    myNeovim &lt;span class="ot"&gt;=&lt;/span&gt; neovim&lt;span class="op"&gt;.&lt;/span&gt;override {&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        vimAlias &lt;span class="ot"&gt;=&lt;/span&gt; true;&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a href="#cb1-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      configure &lt;span class="ot"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb1-7"&gt;&lt;a href="#cb1-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        customRC &lt;span class="ot"&gt;=&lt;/span&gt; ''&lt;/span&gt;
&lt;span id="cb1-8"&gt;&lt;a href="#cb1-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    colo murphy&lt;/span&gt;
&lt;span id="cb1-9"&gt;&lt;a href="#cb1-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    set number&lt;/span&gt;
&lt;span id="cb1-10"&gt;&lt;a href="#cb1-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    set encoding&lt;span class="ot"&gt;=&lt;/span&gt;utf&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;8&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-11"&gt;&lt;a href="#cb1-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    au &lt;span class="dt"&gt;FileType&lt;/span&gt; python setlocal formatprg&lt;span class="ot"&gt;=&lt;/span&gt;autopep8\ &lt;span class="op"&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-12"&gt;&lt;a href="#cb1-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb1-13"&gt;&lt;a href="#cb1-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    function&lt;span class="op"&gt;!&lt;/span&gt; &lt;span class="dt"&gt;DoPrettyXML&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb1-14"&gt;&lt;a href="#cb1-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;let&lt;/span&gt; l&lt;span class="op"&gt;:&lt;/span&gt;origft &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="op"&gt;&amp;amp;&lt;/span&gt;ft&lt;/span&gt;
&lt;span id="cb1-15"&gt;&lt;a href="#cb1-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      set ft&lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-16"&gt;&lt;a href="#cb1-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      1s&lt;span class="op"&gt;/&amp;lt;?&lt;/span&gt;xml &lt;span class="op"&gt;.*?&amp;gt;//&lt;/span&gt;e&lt;/span&gt;
&lt;span id="cb1-17"&gt;&lt;a href="#cb1-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      0put &lt;span class="ot"&gt;=&lt;/span&gt;'&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dt"&gt;PrettyXML&lt;/span&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;'&lt;/span&gt;
&lt;span id="cb1-18"&gt;&lt;a href="#cb1-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;$&lt;/span&gt;put &lt;span class="ot"&gt;=&lt;/span&gt;'&lt;span class="op"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="dt"&gt;PrettyXML&lt;/span&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;'&lt;/span&gt;
&lt;span id="cb1-19"&gt;&lt;a href="#cb1-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      silent &lt;span class="op"&gt;%!&lt;/span&gt;xmllint &lt;span class="co"&gt;--format -&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-20"&gt;&lt;a href="#cb1-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      2d&lt;/span&gt;
&lt;span id="cb1-21"&gt;&lt;a href="#cb1-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;$&lt;/span&gt;d&lt;/span&gt;
&lt;span id="cb1-22"&gt;&lt;a href="#cb1-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-23"&gt;&lt;a href="#cb1-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      exe &lt;span class="st"&gt;"set ft="&lt;/span&gt; &lt;span class="op"&gt;.&lt;/span&gt; l&lt;span class="op"&gt;:&lt;/span&gt;origft&lt;/span&gt;
&lt;span id="cb1-24"&gt;&lt;a href="#cb1-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    endfunction&lt;/span&gt;
&lt;span id="cb1-25"&gt;&lt;a href="#cb1-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    command&lt;span class="op"&gt;!&lt;/span&gt; &lt;span class="dt"&gt;PrettyXML&lt;/span&gt; call &lt;span class="dt"&gt;DoPrettyXML&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb1-26"&gt;&lt;a href="#cb1-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        '';&lt;/span&gt;
&lt;span id="cb1-27"&gt;&lt;a href="#cb1-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        packages&lt;span class="op"&gt;.&lt;/span&gt;myVimPackage &lt;span class="ot"&gt;=&lt;/span&gt; with pkgs&lt;span class="op"&gt;.&lt;/span&gt;vimPlugins; {&lt;/span&gt;
&lt;span id="cb1-28"&gt;&lt;a href="#cb1-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          start &lt;span class="ot"&gt;=&lt;/span&gt; [ &lt;/span&gt;
&lt;span id="cb1-29"&gt;&lt;a href="#cb1-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        airline&lt;/span&gt;
&lt;span id="cb1-30"&gt;&lt;a href="#cb1-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        vim&lt;span class="op"&gt;-&lt;/span&gt;nix&lt;/span&gt;
&lt;span id="cb1-31"&gt;&lt;a href="#cb1-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        molokai&lt;/span&gt;
&lt;span id="cb1-32"&gt;&lt;a href="#cb1-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        tagbar&lt;/span&gt;
&lt;span id="cb1-33"&gt;&lt;a href="#cb1-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        easymotion&lt;/span&gt;
&lt;span id="cb1-34"&gt;&lt;a href="#cb1-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        nerdtree&lt;/span&gt;
&lt;span id="cb1-35"&gt;&lt;a href="#cb1-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        readline&lt;span class="op"&gt;-&lt;/span&gt;vim&lt;/span&gt;
&lt;span id="cb1-36"&gt;&lt;a href="#cb1-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       ];&lt;/span&gt;
&lt;span id="cb1-37"&gt;&lt;a href="#cb1-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          opt &lt;span class="ot"&gt;=&lt;/span&gt; [ ];&lt;/span&gt;
&lt;span id="cb1-38"&gt;&lt;a href="#cb1-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        };      &lt;/span&gt;
&lt;span id="cb1-39"&gt;&lt;a href="#cb1-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    };&lt;/span&gt;
&lt;span id="cb1-40"&gt;&lt;a href="#cb1-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  };&lt;/span&gt;
&lt;span id="cb1-41"&gt;&lt;a href="#cb1-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    myPackages &lt;span class="ot"&gt;=&lt;/span&gt; pkgs&lt;span class="op"&gt;.&lt;/span&gt;buildEnv {&lt;/span&gt;
&lt;span id="cb1-42"&gt;&lt;a href="#cb1-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      name &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="st"&gt;"myPackages"&lt;/span&gt;;&lt;/span&gt;
&lt;span id="cb1-43"&gt;&lt;a href="#cb1-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      paths &lt;span class="ot"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb1-44"&gt;&lt;a href="#cb1-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        myNeovim&lt;/span&gt;
&lt;span id="cb1-45"&gt;&lt;a href="#cb1-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        vlc&lt;/span&gt;
&lt;span id="cb1-46"&gt;&lt;a href="#cb1-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      ];&lt;/span&gt;
&lt;span id="cb1-47"&gt;&lt;a href="#cb1-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    };&lt;/span&gt;
&lt;span id="cb1-48"&gt;&lt;a href="#cb1-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  };&lt;/span&gt;
&lt;span id="cb1-49"&gt;&lt;a href="#cb1-49" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# it is possible to refresh the channels &lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;nix-channel&lt;/span&gt; &lt;span class="at"&gt;--update&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# it is possible to install an apply both vimrc/packages from this command:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;nix-env&lt;/span&gt; &lt;span class="at"&gt;-i&lt;/span&gt; myPackages&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# it is possible to remove this by doing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;nix-env&lt;/span&gt; &lt;span class="at"&gt;-e&lt;/span&gt; myPackages&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Easy neovim with nix — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2020-06-06 22:05&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/easy-neovim-with-nix" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/spark-interactions-with-postgres</id>
    <title>Spark interactions with
Postgres</title>
    <updated>2020-06-06T22:05:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2019-08-24&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="spark-interactions-with-postgres"&gt;Spark interactions with
Postgres&lt;/h1&gt;
&lt;p&gt;Both spark and sqoop allow nativelly to ingest/load relational
databases such postgresql. After being disapointed by both, I have
finally developped an optimized library to better bridge spark and
postgres: reading from postgres, writing to postgres from spark.&lt;/p&gt;
&lt;h1 id="the-spark-postgres-library"&gt;The spark-postgres library&lt;/h1&gt;
&lt;h1 id="comparison-with-sqoop"&gt;Comparison with Sqoop&lt;/h1&gt;
&lt;h1 id="automation-with-yaml"&gt;Automation with yaml&lt;/h1&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Spark interactions with
Postgres — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2020-06-06 22:05&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/spark-interactions-with-postgres" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/fhir-search-engine-resource-operators</id>
    <title>FHIR Search Engine -
Resource Operators</title>
    <updated>2020-06-06T22:05:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;span&gt;Date:&lt;time id="post-date"&gt;2019-10-12&lt;/time&gt;&lt;/span&gt;
&lt;p&gt;Estimated Time:&lt;span id="reading-time"&gt;2 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="fhir-search-engine---resource-operators"&gt;FHIR Search Engine -
Resource Operators&lt;/h1&gt;
&lt;h1 id="technical-consideration"&gt;Technical Consideration&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;solr de-normalization faster selection query performances and
expressivity&lt;/li&gt;
&lt;li&gt;solr de-normalization slower update perforamces and add
complexity&lt;/li&gt;
&lt;li&gt;solr-join can be used in solr-cloud - the joined collection SHALL be
replicated over every shard.&lt;/li&gt;
&lt;li&gt;solr-join performances are linear among the size of the joined
collection (local parameter: score=none).&lt;/li&gt;
&lt;li&gt;solr-join query time is up to 1 sec on a 1M sized collection.&lt;/li&gt;
&lt;li&gt;solr-join only implements inner joins without access to the joined
collection fields&lt;/li&gt;
&lt;li&gt;spark-solr provides fast access to solr-cloud fields with
docValues=true or type string, long, timestamp&lt;/li&gt;
&lt;li&gt;spark-solr produces a dataframe from a solr-cloud collection thought
the /export streaming expression handler&lt;/li&gt;
&lt;li&gt;spark-solr supports any query filters to subset the collection&lt;/li&gt;
&lt;li&gt;spark-solr offers a large set of joins, intersect, union,
aggregation and windowing&lt;/li&gt;
&lt;li&gt;fhir _query search, allows top down search - Observation from
patient with identifier&lt;/li&gt;
&lt;li&gt;fhir _has allows bottom-up search - Patient having Observation with
coding&lt;/li&gt;
&lt;li&gt;fhir _graphql does not allow temporal operators (?)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="technical-conclusion"&gt;Technical Conclusion&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;solr-join are not compatible with large tables&lt;/li&gt;
&lt;li&gt;top-down-search can be implemented with solr de-normalized /
solr-join&lt;/li&gt;
&lt;li&gt;top-down-search prefers solr-denormalized since the joined
collection are huge (patient/encounter)&lt;/li&gt;
&lt;li&gt;the de-normalization can cover patient/encounter details - spark can
fetch them from the patient/encounter delta files (including the
_lastUpdated)&lt;/li&gt;
&lt;li&gt;the _has covers &lt;span class="title-ref"&gt;and&lt;/span&gt; operator but
lacks &lt;span class="title-ref"&gt;or&lt;/span&gt;, &lt;span class="title-ref"&gt;exept&lt;/span&gt;, &lt;span class="title-ref"&gt;after&lt;/span&gt;,
&lt;span class="title-ref"&gt;before&lt;/span&gt;, &lt;span class="title-ref"&gt;not&lt;/span&gt;, &lt;span class="title-ref"&gt;count&lt;/span&gt; and
operator scope &lt;span class="title-ref"&gt;(&lt;/span&gt; and &lt;span class="title-ref"&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;the _has could be implemented by creating a dedicated collection
with all resources in it.&lt;/li&gt;
&lt;li&gt;the _has could be implemented with spark-solr with &lt;span class="title-ref"&gt;and&lt;/span&gt; operators only (patients semi-left
joins)&lt;/li&gt;
&lt;li&gt;adding a long &lt;span class="title-ref"&gt;patient&lt;/span&gt; field to the
fhir patient resource will be usefull&lt;/li&gt;
&lt;li&gt;faceting, and unique faceting fields and denormalized fields
(extension in the bundle)&lt;/li&gt;
&lt;li&gt;&lt;span class="title-ref"&gt;[Base]/Condition?patient.identifier=xxx&amp;amp;encounter.lenght=10&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="implementation"&gt;Implementation&lt;/h1&gt;
&lt;p&gt;It is possible from &lt;span class="title-ref"&gt;spring-data-solr&lt;/span&gt;
to build the solr query. This query can be passed to &lt;span class="title-ref"&gt;spark-solr&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;fhir-syntax -&amp;gt; solr-syntax&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(Condition?active=false) AFTER(24, recorded-date, created-date)
(Composition?status=canceled&amp;amp;_text=patient&amp;amp;type:below=letter)&lt;/li&gt;
&lt;li&gt;ConditionAphp(q=*:&lt;em&gt;&amp;amp;active=true) AFTER(encounter, 24,
recorded-date, created-date)
CompositionAphp(q=&lt;/em&gt;:*&amp;amp;status=canceled)&lt;/li&gt;
&lt;li&gt;ConditionAphp(q=*:&lt;em&gt;&amp;amp;active=true) AND(encounter)
CompositionAphp(q=&lt;/em&gt;:*&amp;amp;status=canceled)&lt;/li&gt;
&lt;li&gt;AFTER(AND(Condition(query), Composition(query), encounter),
Medication(query), patient, "start-date", "end-date")&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AND(Dataframe, Dataframe, Column) OR(Dataframe, Dataframe, Column)
EXCEPT(Dataframe, Dataframe) AFTER(Dataframe, Dataframe, column, column,
column) OCCURRENCE(Dataframe, number) NOT_IN(Dataframe, Dataframe)&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="im"&gt;org&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="im"&gt;springframework&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="im"&gt;data&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="im"&gt;solr&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="im"&gt;core&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="im"&gt;DefaultQueryParser&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DefaultQueryParser b &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;DefaultQueryParser&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;SimpleSolrMappingContext&lt;/span&gt;&lt;span class="op"&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="bu"&gt;String&lt;/span&gt; z &lt;span class="op"&gt;=&lt;/span&gt; b&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;createQueryStringFromNode&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;search&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;getCriteria&lt;/span&gt;&lt;span class="op"&gt;(),&lt;/span&gt; &lt;span class="kw"&gt;null&lt;/span&gt;&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Things go like this:&lt;/p&gt;
&lt;p&gt;fhir-client: fhir-syntax-operators -&amp;gt; fhir-backend:
fhir-syntax-operator =&amp;gt; solr-syntax-operator -&amp;gt; spark-backend:
parser,joins, results -&amp;gt; create a patient list within solr&lt;/p&gt;
&lt;h1 id="group-versus-list"&gt;Group versus List&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;it is possible to filter resources by Group thanks to reverse
chaining&lt;/li&gt;
&lt;li&gt;&lt;span class="title-ref"&gt;[Base]/Patient?_has:Group:member:_id=xxxx&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="title-ref"&gt;[Base]/Encounter?patient._has:Group:member:_id=xxxx&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="title-ref"&gt;[Base]/Observation?patient._has:Group:member:_id=xxxx&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="title-ref"&gt;[Base]/Composition?patient._has:Group:member:_id=xxxx&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;it is possible to filter resources by List thanks to _list
parameter:&lt;/li&gt;
&lt;li&gt;&lt;span class="title-ref"&gt;[Base]/Patient?_list=xxxx&lt;/span&gt; where _list
is a list of patients&lt;/li&gt;
&lt;li&gt;&lt;span class="title-ref"&gt;[Base]/Encounter?_list=xxxx&lt;/span&gt; where
_list is a list of encounters&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="results-informations"&gt;Results Informations&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;the resulting json should contain:
&lt;ul&gt;
&lt;li&gt;the results on the whole&lt;/li&gt;
&lt;li&gt;the results on the practitioner ward&lt;/li&gt;
&lt;li&gt;the faceting results&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most relevant FHIR ressources have two, three or four of those
elements:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;id&lt;/li&gt;
&lt;li&gt;patient&lt;/li&gt;
&lt;li&gt;encounter&lt;/li&gt;
&lt;li&gt;date&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="patient-level"&gt;Patient Level&lt;/h1&gt;
&lt;p&gt;Every filtered ressource being linked to a &lt;strong&gt;patient&lt;/strong&gt;
it is possible to operate on them all:&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode scala"&gt;&lt;code class="sourceCode scala"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; r0 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;6&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;7&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;Nil&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;toDF&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"patient"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; r1 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;Nil&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;toDF&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"patient"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; r2 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;6&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;Nil&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;toDF&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"patient"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; r3 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;7&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;Nil&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;toDF&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"patient"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;`r1 AND r2 AND NOT r3`:
r1.intersect(r1).join(r3,"patient"::Nil,"leftanti").dropDuplicates.show&lt;/li&gt;
&lt;li&gt;`r1 OR r2 OR NOT r3`:
r1.union(r2).union(r0.join(r3,"patient"::Nil,"leftanti")).dropDuplicates.show&lt;/li&gt;
&lt;li&gt;`(r1 OR r2) AND r3`:
r3.intersect(r1.union(r2)).dropDuplicates.show&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="encounter-level"&gt;Encounter Level&lt;/h1&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode scala"&gt;&lt;code class="sourceCode scala"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; r1 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;((&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="dv"&gt;10&lt;/span&gt;&lt;span class="op"&gt;)::(&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="dv"&gt;11&lt;/span&gt;&lt;span class="op"&gt;)::(&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="dv"&gt;12&lt;/span&gt;&lt;span class="op"&gt;)::&lt;/span&gt;Nil&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;toDF&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"patient"&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"encounter"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; r2 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;((&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="dv"&gt;11&lt;/span&gt;&lt;span class="op"&gt;)::(&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="dv"&gt;12&lt;/span&gt;&lt;span class="op"&gt;)::&lt;/span&gt;Nil&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;toDF&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"patient"&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"encounter"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; r3 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;&lt;span class="dv"&gt;7&lt;/span&gt;&lt;span class="op"&gt;::&lt;/span&gt;Nil&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;toDF&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"patient"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;`r1 SAME_ENC r2`: r1.join(r2, "encounter"::Nil,
"leftsemi").select("patient")&lt;/li&gt;
&lt;li&gt;`r1 SAME_ENC NOT r2`: r1.join(r2, "encounter"::Nil,
"leftanti").select("patient")&lt;/li&gt;
&lt;li&gt;`r1 SAME_ENC r2 OR_PAT r3`: r1.join(r2, "encounter"::Nil,
"leftsemi").select("patient").union(r3)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="date-level"&gt;Date Level&lt;/h1&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode scala"&gt;&lt;code class="sourceCode scala"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; r1 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;((&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="ex"&gt;Date&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;1L&lt;span class="op"&gt;))::(&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="ex"&gt;Date&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;2L&lt;span class="op"&gt;))::&lt;/span&gt;Nil&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;toDF&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"patient"&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"date"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;val&lt;/span&gt; r2 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;((&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="ex"&gt;Date&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;1L&lt;span class="op"&gt;))::(&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="ex"&gt;Date&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;2L&lt;span class="op"&gt;))::&lt;/span&gt;Nil&lt;span class="op"&gt;).&lt;/span&gt;&lt;span class="fu"&gt;toDF&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;"patient"&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"date"&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;`r1 AFTER r2`: r1.join(r2, "encounter"::Nil,
"leftsemi").select("patient")&lt;/li&gt;
&lt;li&gt;`r1 AFTER_24h r2`: r1.as("r1").join(r2.as("r2"), "patient"::Nil,
"left").filter(col("r1.date").&amp;gt;=(expr("r2.date + INTERVAL 24
HOURS")))&lt;/li&gt;
&lt;li&gt;`r1 NOT AFTER_24h r2`: r1.as("r1").join(r2.as("r2"), "patient"::Nil,
"full").filter(col("r1.date").isNull ||
!col("r1.date").&amp;gt;=(col("r2.date")))&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="all-together"&gt;All Together&lt;/h1&gt;
&lt;h1 id="number-of-occurrence"&gt;Number Of Occurrence&lt;/h1&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=FHIR Search Engine -
Resource Operators — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2020-06-06 22:05&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/fhir-search-engine-resource-operators" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/postgres-sd1-and-sc2-strategy-comparison</id>
    <title>Postgres SCD1 and SCD2 strategy comparison</title>
    <updated>2020-06-06T22:05:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; 
&lt;p&gt;&lt;span&gt;Published on &lt;time id="post-date"&gt;2019-11-17&lt;/time&gt;&lt;/span&gt;
&lt;span id="reading-time" style="visibility:hidden;"&gt;5 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;Postgres SCD1 and SCD2 strategy comparison&lt;/h1&gt;
&lt;p&gt;In this experimentation, we will demonstrate that using one CTE which
differentiate both update and insert improve significantly the merge processus for both SCD1 and SCD2&lt;/p&gt;
&lt;h1&gt;Experiment tables&lt;/h1&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&lt;span class="hl kwa"&gt;drop table if exists&lt;/span&gt; target&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;drop table if exists&lt;/span&gt; tmp&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;create table&lt;/span&gt; &lt;span class="hl kwd"&gt;target&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl kwb"&gt;int&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd &lt;span class="hl kwb"&gt;text&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; hash &lt;span class="hl kwb"&gt;int&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; end_datetime &lt;span class="hl kwa"&gt;timestamp&lt;/span&gt;&lt;span class="hl opt"&gt;);&lt;/span&gt;
&lt;span class="hl kwa"&gt;create table&lt;/span&gt; &lt;span class="hl kwd"&gt;tmp&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl kwb"&gt;int&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd &lt;span class="hl kwb"&gt;text&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; hash &lt;span class="hl kwb"&gt;int&lt;/span&gt;&lt;span class="hl opt"&gt;);&lt;/span&gt;
&lt;span class="hl slc"&gt;-- TARGET&lt;/span&gt;
&lt;span class="hl kwa"&gt;insert into&lt;/span&gt; &lt;span class="hl kwd"&gt;target&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;cd&lt;span class="hl opt"&gt;,&lt;/span&gt;hash&lt;span class="hl opt"&gt;)&lt;/span&gt; &lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; g.&lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;as id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl sng"&gt;'jim'&lt;/span&gt; &lt;span class="hl kwa"&gt;as&lt;/span&gt; cd&lt;span class="hl opt"&gt;,&lt;/span&gt; g.&lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;as&lt;/span&gt; hash &lt;span class="hl kwa"&gt;FROM&lt;/span&gt; &lt;span class="hl kwd"&gt;generate_series&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;1&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;10000000&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; g&lt;span class="hl opt"&gt;;&lt;/span&gt;

&lt;span class="hl slc"&gt;-- TMP&lt;/span&gt;
&lt;span class="hl kwa"&gt;insert into&lt;/span&gt; &lt;span class="hl kwd"&gt;tmp&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;cd&lt;span class="hl opt"&gt;,&lt;/span&gt;hash&lt;span class="hl opt"&gt;)&lt;/span&gt; &lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; g.&lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;as id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl sng"&gt;'jim'&lt;/span&gt; &lt;span class="hl kwa"&gt;as&lt;/span&gt; cd&lt;span class="hl opt"&gt;,&lt;/span&gt; g.&lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;as&lt;/span&gt; hash &lt;span class="hl kwa"&gt;FROM&lt;/span&gt; &lt;span class="hl kwd"&gt;generate_series&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;4000000&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;5000000&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; g&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;insert into&lt;/span&gt; &lt;span class="hl kwd"&gt;tmp&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;cd&lt;span class="hl opt"&gt;,&lt;/span&gt;hash&lt;span class="hl opt"&gt;)&lt;/span&gt; &lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; g.&lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;as id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl sng"&gt;'john'&lt;/span&gt; &lt;span class="hl kwa"&gt;as&lt;/span&gt; cd&lt;span class="hl opt"&gt;,&lt;/span&gt; g.&lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;as&lt;/span&gt; hash &lt;span class="hl kwa"&gt;FROM&lt;/span&gt; &lt;span class="hl kwd"&gt;generate_series&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;4000000&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;5000000&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; g&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;insert into&lt;/span&gt; &lt;span class="hl kwd"&gt;tmp&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;cd&lt;span class="hl opt"&gt;,&lt;/span&gt;hash&lt;span class="hl opt"&gt;)&lt;/span&gt; &lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; g.&lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;as id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl sng"&gt;'john'&lt;/span&gt; &lt;span class="hl kwa"&gt;as&lt;/span&gt; cd&lt;span class="hl opt"&gt;,&lt;/span&gt; g.&lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;as&lt;/span&gt; hash &lt;span class="hl kwa"&gt;FROM&lt;/span&gt; &lt;span class="hl kwd"&gt;generate_series&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;14000000&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;15000000&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; g&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Atomic implementation scd1&lt;/h1&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&lt;span class="hl kwa"&gt;BEGIN&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;LOCK TABLE&lt;/span&gt; target &lt;span class="hl kwa"&gt;IN EXCLUSIVE MODE&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;explain analyse&lt;/span&gt; 
&lt;span class="hl kwa"&gt;with&lt;/span&gt; fj &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
   &lt;span class="hl kwa"&gt;select&lt;/span&gt; 
   tmp.&lt;span class="hl opt"&gt;*&lt;/span&gt;
   &lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;case when&lt;/span&gt; targ.&lt;span class="hl kwa"&gt;id is null then false else true end as&lt;/span&gt; upd
   &lt;span class="hl kwa"&gt;from&lt;/span&gt; target targ
   &lt;span class="hl kwa"&gt;full outer join&lt;/span&gt; tmp &lt;span class="hl kwa"&gt;on&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;targ.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
   &lt;span class="hl kwa"&gt;where&lt;/span&gt; targ.&lt;span class="hl kwa"&gt;id is null or&lt;/span&gt; targ.hash &lt;span class="hl opt"&gt;!=&lt;/span&gt; tmp.hash
&lt;span class="hl opt"&gt;),&lt;/span&gt;
upd &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
&lt;span class="hl kwa"&gt;update&lt;/span&gt; target targ &lt;span class="hl kwa"&gt;set id&lt;/span&gt;&lt;span class="hl opt"&gt;=&lt;/span&gt;fj.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd&lt;span class="hl opt"&gt;=&lt;/span&gt;fj.cd&lt;span class="hl opt"&gt;,&lt;/span&gt; hash&lt;span class="hl opt"&gt;=&lt;/span&gt;fj.hash 
&lt;span class="hl kwa"&gt;from&lt;/span&gt; fj 
&lt;span class="hl kwa"&gt;where&lt;/span&gt; fj.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; targ.&lt;span class="hl kwa"&gt;id&lt;/span&gt; 
&lt;span class="hl kwa"&gt;and&lt;/span&gt; fj.upd &lt;span class="hl kwa"&gt;is true&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;insert into&lt;/span&gt; target &lt;span class="hl kwa"&gt;select id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd&lt;span class="hl opt"&gt;,&lt;/span&gt; hash &lt;span class="hl kwa"&gt;from&lt;/span&gt; fj &lt;span class="hl kwa"&gt;where&lt;/span&gt; fj.upd &lt;span class="hl kwa"&gt;is false&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;ROLLBACK&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl slc"&gt;--                                                                   QUERY PLAN                                                                  &lt;/span&gt;
&lt;span class="hl slc"&gt;-- ----------------------------------------------------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Insert on target  (cost=1139239.61..1364236.44 rows=49999 width=48) (actual time=6858.761..6858.761 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE fj&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Hash Full Join  (cost=318113.85..515190.96 rows=9999859 width=44) (actual time=3340.633..5629.141 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            Hash Cond: (tmp.id = targ.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            Filter: ((targ.id IS NULL) OR (targ.hash &amp;lt;&amp;gt; tmp.hash))&lt;/span&gt;
&lt;span class="hl slc"&gt;--            Rows Removed by Filter: 11000001&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Seq Scan on tmp  (cost=0.00..46217.03 rows=3000003 width=12) (actual time=0.007..227.686 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Hash  (cost=154053.60..154053.60 rows=9999860 width=8) (actual time=2919.111..2919.111 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Buckets: 131072  Batches: 256  Memory Usage: 2553kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Seq Scan on target targ  (cost=0.00..154053.60 rows=9999860 width=8) (actual time=0.042..1421.153 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE upd&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Update on target targ_1  (cost=337644.85..624048.65 rows=49999 width=118) (actual time=109.975..109.975 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Hash Join  (cost=337644.85..624048.65 rows=49999 width=118) (actual time=109.974..109.974 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Hash Cond: (fj_1.id = targ_1.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  CTE Scan on fj fj_1  (cost=0.00..224996.83 rows=49999 width=104) (actual time=109.973..109.973 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        Filter: (type = 'update'::text)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        Rows Removed by Filter: 1000001&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Hash  (cost=154053.60..154053.60 rows=9999860 width=18) (never executed)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        -&amp;gt;  Seq Scan on target targ_1  (cost=0.00..154053.60 rows=9999860 width=18) (never executed)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    -&amp;gt;  CTE Scan on fj  (cost=0.00..224996.83 rows=49999 width=48) (actual time=3340.639..6016.017 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          Filter: (type = 'insert'::text)&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Planning time: 0.518 ms&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Execution time: 6974.737 ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&lt;span class="hl kwa"&gt;BEGIN&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;explain analyse&lt;/span&gt; 
&lt;span class="hl kwa"&gt;with&lt;/span&gt; u &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
&lt;span class="hl kwa"&gt;UPDATE&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SET id&lt;/span&gt;&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.cd&lt;span class="hl opt"&gt;,&lt;/span&gt; hash&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.hash
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id&lt;/span&gt;
&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT INTO&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; tmp.&lt;span class="hl opt"&gt;*&lt;/span&gt;
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;LEFT OUTER JOIN&lt;/span&gt; target &lt;span class="hl kwa"&gt;ON&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;target.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id IS NULL&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;ROLLBACK&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl slc"&gt;--                                                                         QUERY PLAN                                                                        &lt;/span&gt;
&lt;span class="hl slc"&gt;-- ----------------------------------------------------------------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Insert on target  (cost=945906.04..1113139.12 rows=1 width=20) (actual time=5206.659..5206.659 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE u&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Update on target target_2  (cost=371406.47..595983.57 rows=3000003 width=32) (actual time=8586.434..8586.434 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Hash Join  (cost=371406.47..595983.57 rows=3000003 width=32) (actual time=2899.041..5459.650 rows=2000002 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Hash Cond: (tmp_1.id = target_2.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Seq Scan on tmp tmp_1  (cost=0.00..46217.03 rows=3000003 width=18) (actual time=0.024..403.061 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Hash  (cost=169457.54..169457.54 rows=10999754 width=18) (actual time=2896.588..2896.588 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        Buckets: 65536  Batches: 256  Memory Usage: 2195kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        -&amp;gt;  Seq Scan on target target_2  (cost=0.00..169457.54 rows=10999754 width=18) (actual time=0.012..1319.621 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    -&amp;gt;  Hash Anti Join  (cost=349922.47..517155.54 rows=1 width=20) (actual time=3003.185..4367.119 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          Hash Cond: (tmp.id = target_1.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          -&amp;gt;  Seq Scan on tmp  (cost=0.00..46217.03 rows=3000003 width=12) (actual time=0.027..220.187 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          -&amp;gt;  Hash  (cost=169457.54..169457.54 rows=10999754 width=4) (actual time=2591.285..2591.285 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                Buckets: 131072  Batches: 256  Memory Usage: 2400kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                -&amp;gt;  Seq Scan on target target_1  (cost=0.00..169457.54 rows=10999754 width=4) (actual time=0.035..1162.839 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Planning time: 0.206 ms&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Execution time: 13793.154 ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&lt;span class="hl kwa"&gt;BEGIN&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;explain analyse&lt;/span&gt;
&lt;span class="hl kwa"&gt;with&lt;/span&gt; u &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
&lt;span class="hl kwa"&gt;UPDATE&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SET id&lt;/span&gt;&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.cd&lt;span class="hl opt"&gt;,&lt;/span&gt; hash&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.hash
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id&lt;/span&gt;
&lt;span class="hl kwa"&gt;returning&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id&lt;/span&gt;
&lt;span class="hl opt"&gt;),&lt;/span&gt;
i &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
&lt;span class="hl kwa"&gt;select&lt;/span&gt; tmp.&lt;span class="hl opt"&gt;*&lt;/span&gt;
&lt;span class="hl kwa"&gt;from&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;left join&lt;/span&gt; u &lt;span class="hl kwa"&gt;using&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;where&lt;/span&gt; u.&lt;span class="hl kwa"&gt;id is null&lt;/span&gt;
&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT INTO&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; i.&lt;span class="hl opt"&gt;*&lt;/span&gt;
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; i
&lt;span class="hl kwa"&gt;LEFT OUTER JOIN&lt;/span&gt; target &lt;span class="hl kwa"&gt;ON&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;target.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; i.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id IS NULL&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;ROLLBACK&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl slc"&gt;--                                                                         QUERY PLAN                                                                        &lt;/span&gt;
&lt;span class="hl slc"&gt;-- ----------------------------------------------------------------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Insert on target  (cost=2111532.64..2235532.95 rows=750001 width=48) (actual time=17158.676..17158.676 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE u&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Update on target target_2  (cost=438935.84..682731.95 rows=3000003 width=32) (actual time=2858.907..8387.049 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Hash Join  (cost=438935.84..682731.95 rows=3000003 width=32) (actual time=2858.892..5487.211 rows=2000002 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Hash Cond: (tmp.id = target_2.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Seq Scan on tmp  (cost=0.00..46217.03 rows=3000003 width=18) (actual time=0.026..376.514 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Hash  (cost=200268.26..200268.26 rows=12999726 width=18) (actual time=2856.471..2856.471 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        Buckets: 65536  Batches: 256  Memory Usage: 2195kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        -&amp;gt;  Seq Scan on target target_2  (cost=0.00..200268.26 rows=12999726 width=18) (actual time=0.014..1352.460 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE i&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Merge Anti Join  (cost=936289.71..1015254.85 rows=1500002 width=12) (actual time=10701.594..10942.156 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            Merge Cond: (tmp_1.id = u.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Sort  (cost=471508.34..479008.35 rows=3000003 width=12) (actual time=1143.032..1468.744 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Sort Key: tmp_1.id&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Sort Method: external merge  Disk: 72464kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Seq Scan on tmp tmp_1  (cost=0.00..46217.03 rows=3000003 width=12) (actual time=0.075..266.799 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Sort  (cost=464781.37..472281.38 rows=3000003 width=4) (actual time=8993.435..9113.745 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Sort Key: u.id&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Sort Method: external merge  Disk: 13800kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  CTE Scan on u  (cost=0.00..60000.06 rows=3000003 width=4) (actual time=2858.909..8670.080 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    -&amp;gt;  Hash Anti Join  (cost=413545.84..537546.15 rows=750001 width=48) (actual time=13088.538..15120.417 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          Hash Cond: (i.id = target_1.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          -&amp;gt;  CTE Scan on i  (cost=0.00..30000.04 rows=1500002 width=40) (actual time=10701.598..11209.117 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          -&amp;gt;  Hash  (cost=200268.26..200268.26 rows=12999726 width=4) (actual time=2386.139..2386.139 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                Buckets: 131072  Batches: 256  Memory Usage: 2400kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                -&amp;gt;  Seq Scan on target target_1  (cost=0.00..200268.26 rows=12999726 width=4) (actual time=0.025..1091.998 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Planning time: 0.474 ms&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Execution time: 17204.783 ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&lt;span class="hl kwa"&gt;BEGIN&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;explain ANALYSE with&lt;/span&gt; u &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT INTO&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; tmp.&lt;span class="hl opt"&gt;*&lt;/span&gt;
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;LEFT OUTER JOIN&lt;/span&gt; target &lt;span class="hl kwa"&gt;ON&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;target.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id IS NULL&lt;/span&gt;
&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;UPDATE&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SET id&lt;/span&gt;&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.cd&lt;span class="hl opt"&gt;,&lt;/span&gt; hash&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.hash
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;ROLLBACK&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl slc"&gt;--                                                                        QUERY PLAN                                                                        &lt;/span&gt;
&lt;span class="hl slc"&gt;-- ---------------------------------------------------------------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Update on target  (cost=1181490.50..1444504.63 rows=3000003 width=32) (actual time=8281.352..8281.352 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE u&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Insert on target target_1  (cost=477168.21..675026.30 rows=1 width=20) (actual time=5430.576..5430.576 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Hash Anti Join  (cost=477168.21..675026.30 rows=1 width=20) (actual time=2954.507..4443.851 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Hash Cond: (tmp_1.id = target_2.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Seq Scan on tmp tmp_1  (cost=0.00..46217.03 rows=3000003 width=12) (actual time=0.019..256.940 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Hash  (cost=231078.98..231078.98 rows=14999698 width=4) (actual time=2520.272..2520.272 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        Buckets: 131072  Batches: 256  Memory Usage: 2400kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        -&amp;gt;  Seq Scan on target target_2  (cost=0.00..231078.98 rows=14999698 width=4) (actual time=0.014..1175.381 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    -&amp;gt;  Hash Join  (cost=506464.21..769478.33 rows=3000003 width=32) (actual time=2964.008..5611.788 rows=2000002 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          Hash Cond: (tmp.id = target.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          -&amp;gt;  Seq Scan on tmp  (cost=0.00..46217.03 rows=3000003 width=18) (actual time=0.071..429.298 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          -&amp;gt;  Hash  (cost=231078.98..231078.98 rows=14999698 width=18) (actual time=2961.366..2961.366 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                Buckets: 65536  Batches: 256  Memory Usage: 2195kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                -&amp;gt;  Seq Scan on target  (cost=0.00..231078.98 rows=14999698 width=18) (actual time=0.034..1409.287 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Planning time: 0.424 ms&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Execution time: 13712.030 ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&lt;span class="hl esc"&gt;\t&lt;/span&gt;iming
&lt;span class="hl kwa"&gt;BEGIN&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;UPDATE&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SET id&lt;/span&gt;&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.cd&lt;span class="hl opt"&gt;,&lt;/span&gt; hash&lt;span class="hl opt"&gt;=&lt;/span&gt;tmp.hash
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT INTO&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; tmp.&lt;span class="hl opt"&gt;*&lt;/span&gt;
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;LEFT OUTER JOIN&lt;/span&gt; target &lt;span class="hl kwa"&gt;ON&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;target.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id IS NULL&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;ROLLBACK&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl slc"&gt;-- Time: 5329,939 ms (00:05,330)&lt;/span&gt;
&lt;span class="hl slc"&gt;-- Time: 12554,331 ms (00:12,554)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Atomic implementation scd2&lt;/h1&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&lt;span class="hl kwa"&gt;begin&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;explain analyse&lt;/span&gt;
&lt;span class="hl kwa"&gt;with&lt;/span&gt; i &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT INTO&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; tmp.&lt;span class="hl opt"&gt;*&lt;/span&gt;
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;LEFT OUTER JOIN&lt;/span&gt; target &lt;span class="hl kwa"&gt;ON&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;target.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id IS NULL&lt;/span&gt;
&lt;span class="hl opt"&gt;),&lt;/span&gt; 
u &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT INTO&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SELECT&lt;/span&gt; tmp.&lt;span class="hl opt"&gt;*&lt;/span&gt;
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
&lt;span class="hl kwa"&gt;JOIN&lt;/span&gt; target &lt;span class="hl kwa"&gt;ON&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;target.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; target.hash &lt;span class="hl kwa"&gt;is distinct from&lt;/span&gt; tmp.hash
&lt;span class="hl kwa"&gt;returning&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id&lt;/span&gt;
&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;UPDATE&lt;/span&gt; target
&lt;span class="hl kwa"&gt;SET&lt;/span&gt; end_datetime &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl kwd"&gt;now&lt;/span&gt;&lt;span class="hl opt"&gt;()&lt;/span&gt;
&lt;span class="hl kwa"&gt;FROM&lt;/span&gt; u
&lt;span class="hl kwa"&gt;WHERE&lt;/span&gt; u.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; target.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;rollback&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl slc"&gt;--                                                                        QUERY PLAN                                                                       &lt;/span&gt;
&lt;span class="hl slc"&gt;-- --------------------------------------------------------------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Update on target  (cost=1560116.39..1800721.53 rows=3000003 width=54) (actual time=6156.396..6156.396 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE i&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Insert on target target_1  (cost=400062.40..552387.47 rows=1 width=20) (actual time=8926.725..8926.725 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Hash Anti Join  (cost=400062.40..552387.47 rows=1 width=20) (actual time=3602.728..5597.313 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Hash Cond: (tmp.id = target_2.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Seq Scan on tmp  (cost=0.00..46217.03 rows=3000003 width=12) (actual time=0.450..300.704 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Hash  (cost=250713.29..250713.29 rows=9103129 width=4) (actual time=3092.523..3092.523 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        Buckets: 131072  Batches: 128  Memory Usage: 3781kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        -&amp;gt;  Seq Scan on target target_2  (cost=0.00..250713.29 rows=9103129 width=4) (actual time=0.010..1519.702 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE u&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Insert on target target_3  (cost=400062.40..589887.51 rows=3000003 width=20) (actual time=6156.392..6156.393 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Hash Join  (cost=400062.40..589887.51 rows=3000003 width=20) (actual time=6156.391..6156.391 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Hash Cond: (tmp_1.id = target_4.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Join Filter: (target_4.hash IS DISTINCT FROM tmp_1.hash)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Rows Removed by Join Filter: 2000002&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Seq Scan on tmp tmp_1  (cost=0.00..46217.03 rows=3000003 width=12) (actual time=0.013..334.453 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Hash  (cost=250713.29..250713.29 rows=9103129 width=8) (actual time=3359.346..3359.346 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        Buckets: 131072 (originally 131072)  Batches: 256 (originally 128)  Memory Usage: 4087kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        -&amp;gt;  Seq Scan on target target_4  (cost=0.00..250713.29 rows=9103129 width=8) (actual time=0.014..1677.709 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    -&amp;gt;  Hash Join  (cost=417841.40..658446.55 rows=3000003 width=54) (actual time=6156.394..6156.395 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          Hash Cond: (u.id = target.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          -&amp;gt;  CTE Scan on u  (cost=0.00..60000.06 rows=3000003 width=32) (actual time=6156.394..6156.394 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--          -&amp;gt;  Hash  (cost=250713.29..250713.29 rows=9103129 width=18) (never executed)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                -&amp;gt;  Seq Scan on target  (cost=0.00..250713.29 rows=9103129 width=18) (never executed)&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Planning time: 0.220 ms&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Execution time: 15083.304 ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&lt;span class="hl kwa"&gt;begin&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;explain analyze&lt;/span&gt;
&lt;span class="hl kwa"&gt;with&lt;/span&gt; tmp &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
&lt;span class="hl kwa"&gt;select&lt;/span&gt; 
tmp.&lt;span class="hl opt"&gt;*&lt;/span&gt;
&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;case when&lt;/span&gt; targ.&lt;span class="hl kwa"&gt;id is null then false else true end as&lt;/span&gt; upd
&lt;span class="hl kwa"&gt;from&lt;/span&gt; target targ
&lt;span class="hl kwa"&gt;full outer join&lt;/span&gt; tmp &lt;span class="hl kwa"&gt;on&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;targ.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;span class="hl kwa"&gt;where&lt;/span&gt; targ.&lt;span class="hl kwa"&gt;id is null or&lt;/span&gt; targ.hash &lt;span class="hl opt"&gt;!=&lt;/span&gt; tmp.hash
 &lt;span class="hl opt"&gt;),&lt;/span&gt; 
 u &lt;span class="hl kwa"&gt;as&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;
 &lt;span class="hl kwa"&gt;UPDATE&lt;/span&gt; target
 &lt;span class="hl kwa"&gt;SET&lt;/span&gt; end_datetime &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl kwd"&gt;now&lt;/span&gt;&lt;span class="hl opt"&gt;()&lt;/span&gt;
 &lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp
 &lt;span class="hl kwa"&gt;where&lt;/span&gt; 
 target.&lt;span class="hl kwa"&gt;id&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; tmp.&lt;span class="hl kwa"&gt;id&lt;/span&gt;
 &lt;span class="hl kwa"&gt;AND&lt;/span&gt; tmp.upd &lt;span class="hl kwa"&gt;is true&lt;/span&gt;
 &lt;span class="hl opt"&gt;)&lt;/span&gt;
 &lt;span class="hl kwa"&gt;INSERT INTO&lt;/span&gt; &lt;span class="hl kwd"&gt;target&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd&lt;span class="hl opt"&gt;,&lt;/span&gt; hash&lt;span class="hl opt"&gt;)&lt;/span&gt;
 &lt;span class="hl kwa"&gt;SELECT id&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; cd&lt;span class="hl opt"&gt;,&lt;/span&gt; hash
 &lt;span class="hl kwa"&gt;FROM&lt;/span&gt; tmp&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;rollback&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl slc"&gt;--                                                                   QUERY PLAN                                                                  &lt;/span&gt;
&lt;span class="hl slc"&gt;-- ----------------------------------------------------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Insert on target  (cost=1166655991509.07..1166656191396.43 rows=9994368 width=48) (actual time=8666.204..8666.204 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE tmp&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Hash Full Join  (cost=438165.30..635221.42 rows=9994368 width=13) (actual time=4531.084..7278.771 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            Hash Cond: (tmp_1.id = targ.id)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            Filter: ((targ.id IS NULL) OR (targ.hash &amp;lt;&amp;gt; tmp_1.hash))&lt;/span&gt;
&lt;span class="hl slc"&gt;--            Rows Removed by Filter: 11000001&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Seq Scan on tmp tmp_1  (cost=0.00..46217.03 rows=3000003 width=12) (actual time=0.140..307.256 rows=3000003 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Hash  (cost=274194.69..274194.69 rows=9994369 width=8) (actual time=3974.719..3974.719 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  Buckets: 131072  Batches: 256  Memory Usage: 2553kB&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Seq Scan on target targ  (cost=0.00..274194.69 rows=9994369 width=8) (actual time=0.059..2009.929 rows=10000000 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    CTE u&lt;/span&gt;
&lt;span class="hl slc"&gt;--      -&amp;gt;  Update on target target_1  (cost=0.00..1166655356287.65 rows=49943700856896 width=50) (actual time=98.574..98.574 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--            -&amp;gt;  Nested Loop  (cost=0.00..1166655356287.65 rows=49943700856896 width=50) (actual time=98.573..98.573 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  CTE Scan on tmp tmp_2  (cost=0.00..199887.36 rows=4997184 width=24) (actual time=98.572..98.572 rows=0 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        Filter: (upd IS TRUE)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        Rows Removed by Filter: 1000001&lt;/span&gt;
&lt;span class="hl slc"&gt;--                  -&amp;gt;  Materialize  (cost=0.00..382727.54 rows=9994369 width=18) (never executed)&lt;/span&gt;
&lt;span class="hl slc"&gt;--                        -&amp;gt;  Seq Scan on target target_1  (cost=0.00..274194.69 rows=9994369 width=18) (never executed)&lt;/span&gt;
&lt;span class="hl slc"&gt;--    -&amp;gt;  CTE Scan on tmp  (cost=0.00..199887.36 rows=9994368 width=48) (actual time=4531.092..7663.395 rows=1000001 loops=1)&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Planning time: 0.137 ms&lt;/span&gt;
&lt;span class="hl slc"&gt;--  Execution time: 8769.648 ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Postgres SCD1 and SCD2 strategy comparison — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2020-06-06 22:05&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/postgres-sd1-and-sc2-strategy-comparison" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/first-contact-with-spark-jobserver</id>
    <title>First contact with spark-jobserver</title>
    <updated>2020-06-20T19:02:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; 
  &lt;div id="generated-toc"&gt; &lt;/div&gt;
  &lt;hr&gt;
&lt;p&gt;&lt;span&gt;Published on &lt;time id="post-date"&gt;2019-11-24&lt;/time&gt;&lt;/span&gt;
&lt;span id="reading-time" style="visibility:hidden;"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;First contact with spark-jobserver&lt;/h1&gt;
&lt;p&gt;This describe how to test locally a spark-jobserver instance. &lt;a href="https://github.com/spark-jobserver/"&gt;This derive from the readme&lt;/a&gt;. First impressions are great.&lt;/p&gt;
&lt;h2&gt;Server side&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;git clone git@github.com&lt;span class="hl opt"&gt;:&lt;/span&gt;spark&lt;span class="hl kwb"&gt;-jobserver&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;spark&lt;span class="hl kwb"&gt;-jobserver&lt;/span&gt;.git
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Activate Basic Auth&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;&lt;span class="hl slc"&gt;# add this at the end config/local.conf&lt;/span&gt;
shiro &lt;span class="hl opt"&gt;{&lt;/span&gt;
authentication &lt;span class="hl opt"&gt;=&lt;/span&gt; on
&lt;span class="hl slc"&gt;# absolute path to shiro config file, including file name&lt;/span&gt;
config.path &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl sng"&gt;"config/shiro.ini.basic"&lt;/span&gt;
&lt;span class="hl opt"&gt;}&lt;/span&gt;
&lt;span class="hl slc"&gt;# specify the number of query per slot (default 8)&lt;/span&gt;
spark &lt;span class="hl opt"&gt;{&lt;/span&gt;
jobserver.max&lt;span class="hl opt"&gt;-&lt;/span&gt;jobs&lt;span class="hl opt"&gt;-&lt;/span&gt;per&lt;span class="hl opt"&gt;-&lt;/span&gt;context &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl num"&gt;2&lt;/span&gt;
&lt;span class="hl opt"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://github.com/spark-jobserver/spark-jobserver/blob/2eaa041070e5a4a2f97b01f8903c0f9207b0d452/job-server/src/test/scala/spark/jobserver/JavaJobSpec.scala"&gt;More detail in the source code&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Increase the jar size&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;&lt;span class="hl slc"&gt;# in spark section&lt;/span&gt;
short&lt;span class="hl opt"&gt;-&lt;/span&gt;timeout &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl num"&gt;60&lt;/span&gt; s

&lt;span class="hl slc"&gt;# in root section&lt;/span&gt;
spray.can.server &lt;span class="hl opt"&gt;{&lt;/span&gt;
    parsing.max&lt;span class="hl opt"&gt;-&lt;/span&gt;content&lt;span class="hl opt"&gt;-&lt;/span&gt;length &lt;span class="hl opt"&gt;=&lt;/span&gt; 300m
    idle&lt;span class="hl opt"&gt;-&lt;/span&gt;timeout &lt;span class="hl opt"&gt;=&lt;/span&gt; 400s
    request&lt;span class="hl opt"&gt;-&lt;/span&gt;timeout &lt;span class="hl opt"&gt;=&lt;/span&gt; 300s
&lt;span class="hl opt"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Start the server&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;sbt
&lt;span class="hl slc"&gt;# Run this&lt;/span&gt;
job&lt;span class="hl kwb"&gt;-server-extras&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;reStart config&lt;span class="hl opt"&gt;/&lt;/span&gt;&lt;span class="hl kwb"&gt;local&lt;/span&gt;.conf &lt;span class="hl kwb"&gt;--- -Xmx8g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Client&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;&lt;span class="hl slc"&gt;# compile the jar&lt;/span&gt;
sbt job&lt;span class="hl kwb"&gt;-server-tests&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;package

&lt;span class="hl slc"&gt;# add the jar and give it the "test-binary" name&lt;/span&gt;
curl &lt;span class="hl kwb"&gt;--basic --user&lt;/span&gt; &lt;span class="hl sng"&gt;'user:pwd'&lt;/span&gt; X POST localhost&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;8090&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;binaries&lt;span class="hl opt"&gt;/&lt;/span&gt;&lt;span class="hl kwb"&gt;test-binary -H&lt;/span&gt; &lt;span class="hl sng"&gt;"Content-Type: application/java-archive"&lt;/span&gt; &lt;span class="hl kwb"&gt;--data-binary&lt;/span&gt; @job&lt;span class="hl kwb"&gt;-server-tests&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;target&lt;span class="hl opt"&gt;/&lt;/span&gt;scala&lt;span class="hl kwb"&gt;-2&lt;/span&gt;.11&lt;span class="hl opt"&gt;/&lt;/span&gt;job&lt;span class="hl kwb"&gt;-server-tests_2&lt;/span&gt;.11&lt;span class="hl kwb"&gt;-0&lt;/span&gt;.9&lt;span class="hl num"&gt;.1&lt;/span&gt;&lt;span class="hl kwb"&gt;-SNAPSHOT&lt;/span&gt;.jar

&lt;span class="hl slc"&gt;# pass the basic auth&lt;/span&gt;
curl localhost&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;8090&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;contexts &lt;span class="hl kwb"&gt;--basic --user&lt;/span&gt; &lt;span class="hl sng"&gt;'user:pwd'&lt;/span&gt; &lt;span class="hl kwb"&gt;-d&lt;/span&gt; &lt;span class="hl sng"&gt;""&lt;/span&gt; &lt;span class="hl sng"&gt;"localhost:8090/contexts/test-context?num-cpu-cores=4&amp;amp;memory-per-node=512m"&lt;/span&gt;

&lt;span class="hl slc"&gt;# get the contexts&lt;/span&gt;
curl &lt;span class="hl kwb"&gt;-k --basic --user&lt;/span&gt; &lt;span class="hl sng"&gt;'user:pw'&lt;/span&gt; https&lt;span class="hl opt"&gt;://&lt;/span&gt;localhost&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;8090&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;contexts

&lt;span class="hl slc"&gt;# get the jobs&lt;/span&gt;
curl &lt;span class="hl kwb"&gt;-k --basic --user&lt;/span&gt; &lt;span class="hl sng"&gt;'user:pw'&lt;/span&gt; https&lt;span class="hl opt"&gt;://&lt;/span&gt;localhost&lt;span class="hl opt"&gt;:&lt;/span&gt;&lt;span class="hl num"&gt;8090&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;&lt;span class="hl kwb"&gt;jobs&lt;/span&gt;

&lt;span class="hl slc"&gt;# run a job based on the test-binary file&lt;/span&gt;
&lt;span class="hl slc"&gt;# also make it syncronized and increase the timeout&lt;/span&gt;
curl &lt;span class="hl kwb"&gt;--basic --user&lt;/span&gt; &lt;span class="hl sng"&gt;'user:pwd'&lt;/span&gt; &lt;span class="hl kwb"&gt;-d&lt;/span&gt; &lt;span class="hl sng"&gt;"input.string = a b c a b see"&lt;/span&gt; &lt;span class="hl sng"&gt;"localhost:8090/jobs?appName=test-binary&amp;amp;classPath=spark.jobserver.WordCountExample&amp;amp;context=test-context&amp;amp;sync=true&amp;amp;timeout=100000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Async Client&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;curl &lt;span class="hl opt"&gt;--&lt;/span&gt;basic &lt;span class="hl opt"&gt;--&lt;/span&gt;user user&lt;span class="hl opt"&gt;:&lt;/span&gt;pw' &lt;span class="hl opt"&gt;-&lt;/span&gt;d &lt;span class="hl sng"&gt;"input.string = a b c a b see"&lt;/span&gt; &lt;span class="hl sng"&gt;"localhost:8090/jobs?appName=omop-spark-job&amp;amp;classPath=io.frama.parisni.spark.omop.job.WordCountExample&amp;amp;context=test-context&amp;amp;sync=false&amp;amp;timeout=100000"&lt;/span&gt;
&lt;span class="hl kwa"&gt;{&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"duration"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"Job not done yet"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"classPath"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"io.frama.parisni.spark.omop.job.WordCountExample"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"startTime"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"2020-06-12T16:43:46.980+02:00"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"context"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"test-context"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"status"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"STARTED"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"jobId"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"d492de45-dc1e-4d08-996c-19b47fdb986f"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"contextId"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"47607883-d90c-456e-8884-d160f4c41480"&lt;/span&gt;
&lt;span class="hl kwa"&gt;}&lt;/span&gt;

curl &lt;span class="hl opt"&gt;-&lt;/span&gt;X GET &lt;span class="hl opt"&gt;--&lt;/span&gt;basic &lt;span class="hl opt"&gt;--&lt;/span&gt;user 'user&lt;span class="hl opt"&gt;:&lt;/span&gt;pw' &lt;span class="hl sng"&gt;"localhost:8090/jobs/d492de45-dc1e-4d08-996c-19b47fdb986f"&lt;/span&gt;
&lt;span class="hl kwa"&gt;{&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"duration"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"0.157 secs"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"classPath"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"io.frama.parisni.spark.omop.job.WordCountExample"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"startTime"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"2020-06-12T16:43:46.980+02:00"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"context"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"test-context"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"result"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl kwa"&gt;{&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"b"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;2&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"a"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;2&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"see"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;1&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"c"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;1&lt;/span&gt;
  &lt;span class="hl kwa"&gt;}&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"status"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"FINISHED"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"jobId"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"d492de45-dc1e-4d08-996c-19b47fdb986f"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"contextId"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"47607883-d90c-456e-8884-d160f4c41480"&lt;/span&gt;
&lt;span class="hl kwa"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Enabling sparkContext with hive support&lt;/h2&gt;
&lt;p&gt;By extending the &lt;code&gt;SparkSessionJob&lt;/code&gt; class and using the below code, you get the hive support:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;context&lt;span class="hl kwb"&gt;-create&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt;
        curl &lt;span class="hl kwb"&gt;-X&lt;/span&gt; POST &lt;span class="hl kwb"&gt;-k --basic --user&lt;/span&gt; &lt;span class="hl sng"&gt;'&lt;/span&gt;&lt;span class="hl ipl"&gt;${USER}&lt;/span&gt;&lt;span class="hl sng"&gt;:&lt;/span&gt;&lt;span class="hl ipl"&gt;${PWD}&lt;/span&gt;&lt;span class="hl sng"&gt;'&lt;/span&gt; &lt;span class="hl sng"&gt;"&lt;/span&gt;&lt;span class="hl ipl"&gt;${HOST}&lt;/span&gt;&lt;span class="hl sng"&gt;:&lt;/span&gt;&lt;span class="hl ipl"&gt;${PORT}&lt;/span&gt;&lt;span class="hl sng"&gt;/contexts/test-context?num-cpu-cores=4&amp;amp;memory-per-node=512m&amp;amp;context-factory=spark.jobserver.context.SessionContextFactory"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Complex result (use array/maps as object returned):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;&lt;span class="hl kwa"&gt;{&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"jobId"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"4e85111f-98aa-4736-8153-11f937d4fd2f"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
  &lt;span class="hl kwc"&gt;"result"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl kwb"&gt;[&lt;/span&gt;&lt;span class="hl kwa"&gt;{&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"list"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;1&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"count"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"800"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"resourceType"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"Patient"&lt;/span&gt;
  &lt;span class="hl kwa"&gt;}&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;{&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"list"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;2&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"count"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"100"&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;
    &lt;span class="hl kwc"&gt;"resourceType"&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl sng"&gt;"Condition"&lt;/span&gt;
  &lt;span class="hl kwa"&gt;}&lt;/span&gt;&lt;span class="hl kwb"&gt;]&lt;/span&gt;
&lt;span class="hl kwa"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Passing config parameters&lt;/h2&gt;
&lt;p&gt;One way is to store them into the &lt;code&gt;env.conf&lt;/code&gt; file, in the &lt;code&gt;passthough&lt;/code&gt;
section. They are then accessible from the
&lt;code&gt;runtime.contextConfig&lt;/code&gt;variable within the &lt;code&gt;runJob&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;They can be accessed from code thought &lt;code&gt;val ZK = runtime.contextConfig.getString("passthrough.the.variable")&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Passing extra options&lt;/h2&gt;
&lt;p&gt;This can be done with the &lt;code&gt;env.sh&lt;/code&gt; file. In this example, we configure
the basic auth to solr cloud.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;MANAGER_EXTRA_SPARK_CONFS&lt;span class="hl opt"&gt;=&lt;/span&gt;&lt;span class="hl sng"&gt;"spark.executor.extraJavaOptions=-Dsolr.httpclient.config=&amp;lt;path-to&amp;gt;/auth_qua.txt -Dhdp.version=2.6.5.0-292|spark.driver.extraJavaOptions=-Dhdp.version=2.6.5.0-292,-Dsolr.httpclient.config=&amp;lt;path-to&amp;gt;/auth_qua.txt,spark.yarn.submit.waitAppCompletion=false|spark.files=&lt;/span&gt;&lt;span class="hl ipl"&gt;$appdir&lt;/span&gt;&lt;span class="hl sng"&gt;/log4jcluster.properties,&lt;/span&gt;&lt;span class="hl ipl"&gt;$conffile&lt;/span&gt;&lt;span class="hl sng"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=First contact with spark-jobserver — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2020-06-20 19:02&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/first-contact-with-spark-jobserver" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/book-section</id>
    <title>Introducing the "Readings" section</title>
    <updated>2020-08-04T14:43:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;div id="refman"&gt;
&lt;div id="refman-sidebar"&gt;
  &lt;div id="generated-toc"&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;div id="refman-main"&gt;
&lt;p&gt;&lt;span&gt;Published on &lt;time id="post-date"&gt;2020-03-08&lt;/time&gt;&lt;/span&gt;
&lt;span id="reading-time" style="visibility:hidden;"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;Introducing the "Readings" section&lt;/h1&gt;
&lt;h3&gt;Principle&lt;/h3&gt;
&lt;p&gt;Books are meant to be &lt;strong&gt;read&lt;/strong&gt;. Also books should be &lt;strong&gt;reviewed and
criticized&lt;/strong&gt;. I am introducing a new book section with several goals
in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;read more books&lt;/li&gt;
&lt;li&gt;read carefuly&lt;/li&gt;
&lt;li&gt;keep notes, and summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Content&lt;/h3&gt;
&lt;p&gt;Books, comics, novel, essay, philosophy and also research papers will be covered.
In term of content, I can imagine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reference&lt;/li&gt;
&lt;li&gt;citation&lt;/li&gt;
&lt;li&gt;synthesis&lt;/li&gt;
&lt;li&gt;form analysis&lt;/li&gt;
&lt;li&gt;and also cover picture&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wonder I it's legal to share citations, and pictures of comics. This
is something I will check out.&lt;/p&gt;
&lt;h3&gt;Form&lt;/h3&gt;
&lt;p&gt;I guess I could distinguish several categories, and provide &lt;strong&gt;views per
categories&lt;/strong&gt;.&lt;/p&gt;
&lt;h4&gt;Entry preview&lt;/h4&gt;
&lt;p&gt;Each entry preview would have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;summary&lt;/li&gt;
&lt;li&gt;thumbnail&lt;/li&gt;
&lt;li&gt;stars&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Entry content&lt;/h4&gt;
&lt;p&gt;Depending on the category, each book entry might have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;summary&lt;/li&gt;
&lt;li&gt;screenshots&lt;/li&gt;
&lt;li&gt;citations&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Next Steps&lt;/h3&gt;
&lt;p&gt;I will need to explore existing things on the web. Still the content
and reading can start with this goal. I can think of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://qblog.aaronsw.com/page/7"&gt;raw meat by aaronsw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pinboard.in/u:aaronsw/"&gt;pinboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.aaronsw.com/weblog/"&gt;raw thought&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codepen.io/pun-isher/pen/qjZaXN"&gt;timeline&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Introducing the " readings"="" section="" —="" software="" lobotomy"=""&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2020-08-04 14:43&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/book-section" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/postgresql-versus-greenplum</id>
    <title>Postgresql Versus Greenplum</title>
    <updated>2021-11-07T11:53:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt;   &lt;div id="generated-toc"&gt; &lt;/div&gt;
&lt;p&gt;&lt;span&gt;Published on &lt;time id="post-date"&gt;2020-12-04&lt;/time&gt;&lt;/span&gt;
&lt;span id="reading-time" style="visibility:hidden;"&gt;4 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;Postgresql Versus Greenplum&lt;/h1&gt;
&lt;h2&gt;Server configuration&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;a dataset of 30M/60M and 100M rows&lt;/li&gt;
&lt;li&gt;16GO RAM&lt;/li&gt;
&lt;li&gt;500GO SSD&lt;/li&gt;
&lt;li&gt;8 core&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Postgresql&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;version 13.1&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;madlib 1.17&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;configured with pgtune&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;max_connections = 20
shared_buffers = 4GB
effective_cache_size = 12GB
maintenance_work_mem = 2GB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 500
random_page_cost = 1.1
effective_io_concurrency = 200
work_mem = 26214kB
min_wal_size = 4GB
max_wal_size = 16GB
max_worker_processes = 8
max_parallel_workers_per_gather = 4
max_parallel_workers = 8
max_parallel_maintenance_workers = 4
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Greenplum&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;version 6.12&lt;/li&gt;
&lt;li&gt;madlib 1.17&lt;/li&gt;
&lt;li&gt;4 segments&lt;/li&gt;
&lt;li&gt;default configurations&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Overall results&lt;/h2&gt;
&lt;div&gt;
&lt;img src="/images/pg_vs_gp2.webp" height="700"&gt;
&lt;/div&gt;
&lt;h2&gt;conclusion&lt;/h2&gt;
&lt;p&gt;From this preliminary results, Greeplum is superior to postgreSQL on a
standalone server, which is very surprining because it is supposed to
work on a distrinbuted cluster.&lt;/p&gt;
&lt;p&gt;Greenplum is way faster than postgres in the context of datawarhousing
and managing large tables in every domains:
insert/update/delete/select. It provides a set of tools such gptext,
madlib, map-reduce, pl/python-R and PFX which looks relevant. Also it
provides 'queues' to makes multi-users collaborate better.&lt;/p&gt;
&lt;p&gt;While postgreSQL is effective on a 30M rows table, it struggles to
handle larger tables.&lt;/p&gt;
&lt;h2&gt;SQL&lt;/h2&gt;
&lt;h3&gt;Postgresql&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&lt;span class="hl kwa"&gt;create table&lt;/span&gt; &lt;span class="hl kwd"&gt;labevents&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;
   row_id      &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt; subject_id  &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt; hadm_id     &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt; itemid      &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt; charttime   &lt;span class="hl kwa"&gt;timestamp&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;0&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; &lt;span class="hl kwa"&gt;without time zone&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;value&lt;/span&gt;       &lt;span class="hl kwb"&gt;character&lt;/span&gt; &lt;span class="hl kwa"&gt;varying&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;200&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt; valuenum    &lt;span class="hl kwa"&gt;double precision&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt; valueuom    &lt;span class="hl kwb"&gt;character&lt;/span&gt; &lt;span class="hl kwa"&gt;varying&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;20&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;flag&lt;/span&gt;        &lt;span class="hl kwb"&gt;character&lt;/span&gt; &lt;span class="hl kwa"&gt;varying&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;20&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt; mimic_id    &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;) ;&lt;/span&gt;
&lt;span class="hl kwa"&gt;CREATE TABLE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# \&lt;span class="hl kwa"&gt;copy&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;from&lt;/span&gt; &lt;span class="hl sng"&gt;'labevents.csv'&lt;/span&gt; &lt;span class="hl kwa"&gt;csv&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;COPY&lt;/span&gt; &lt;span class="hl num"&gt;27854055&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;353750.640&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;05&lt;/span&gt;&lt;span class="hl kwc"&gt;:53&lt;/span&gt;.751&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
    c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;18009889&lt;/span&gt; |
  &lt;span class="hl num"&gt;9779594&lt;/span&gt; | abnormal
    &lt;span class="hl num"&gt;64572&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;939.223&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select&lt;/span&gt; c1.row_id&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;row_number&lt;/span&gt;&lt;span class="hl opt"&gt;()&lt;/span&gt; &lt;span class="hl kwa"&gt;over&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;partition by&lt;/span&gt; c1.itemid &lt;span class="hl kwa"&gt;order by&lt;/span&gt; c1.row_id &lt;span class="hl kwa"&gt;desc&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; rk &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
  row_id  | rk
&lt;span class="hl slc"&gt;----------+----&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;1&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;2&lt;/span&gt;
 &lt;span class="hl num"&gt;27906612&lt;/span&gt; |  &lt;span class="hl num"&gt;3&lt;/span&gt;
 &lt;span class="hl num"&gt;27906561&lt;/span&gt; |  &lt;span class="hl num"&gt;4&lt;/span&gt;
 &lt;span class="hl num"&gt;27906550&lt;/span&gt; |  &lt;span class="hl num"&gt;5&lt;/span&gt;
 &lt;span class="hl num"&gt;27906507&lt;/span&gt; |  &lt;span class="hl num"&gt;6&lt;/span&gt;
 &lt;span class="hl num"&gt;27906370&lt;/span&gt; |  &lt;span class="hl num"&gt;7&lt;/span&gt;
 &lt;span class="hl num"&gt;27906325&lt;/span&gt; |  &lt;span class="hl num"&gt;8&lt;/span&gt;
 &lt;span class="hl num"&gt;27906270&lt;/span&gt; |  &lt;span class="hl num"&gt;9&lt;/span&gt;
 &lt;span class="hl num"&gt;27906257&lt;/span&gt; | &lt;span class="hl num"&gt;10&lt;/span&gt;
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;13714.732&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;00&lt;/span&gt;&lt;span class="hl kwc"&gt;:13&lt;/span&gt;.715&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;insert into&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;select&lt;/span&gt; &lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT&lt;/span&gt; &lt;span class="hl num"&gt;0 27854055&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;423631.155&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;07&lt;/span&gt;&lt;span class="hl kwc"&gt;:03&lt;/span&gt;.631&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
    c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;36019778&lt;/span&gt; |
 &lt;span class="hl num"&gt;19559188&lt;/span&gt; | abnormal
   &lt;span class="hl num"&gt;129144&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;5295.608&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;00&lt;/span&gt;&lt;span class="hl kwc"&gt;:05&lt;/span&gt;.296&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select&lt;/span&gt; c1.row_id&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;row_number&lt;/span&gt;&lt;span class="hl opt"&gt;()&lt;/span&gt; &lt;span class="hl kwa"&gt;over&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;partition by&lt;/span&gt; c1.itemid &lt;span class="hl kwa"&gt;order by&lt;/span&gt; c1.row_id &lt;span class="hl kwa"&gt;desc&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; rk &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
  row_id  | rk
&lt;span class="hl slc"&gt;----------+----&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;1&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;2&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;3&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;4&lt;/span&gt;
 &lt;span class="hl num"&gt;27906612&lt;/span&gt; |  &lt;span class="hl num"&gt;5&lt;/span&gt;
 &lt;span class="hl num"&gt;27906612&lt;/span&gt; |  &lt;span class="hl num"&gt;6&lt;/span&gt;
 &lt;span class="hl num"&gt;27906561&lt;/span&gt; |  &lt;span class="hl num"&gt;7&lt;/span&gt;
 &lt;span class="hl num"&gt;27906561&lt;/span&gt; |  &lt;span class="hl num"&gt;8&lt;/span&gt;
 &lt;span class="hl num"&gt;27906550&lt;/span&gt; |  &lt;span class="hl num"&gt;9&lt;/span&gt;
 &lt;span class="hl num"&gt;27906550&lt;/span&gt; | &lt;span class="hl num"&gt;10&lt;/span&gt;
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;126347.700&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;02&lt;/span&gt;&lt;span class="hl kwc"&gt;:06&lt;/span&gt;.348&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1 &lt;span class="hl kwa"&gt;join&lt;/span&gt; labevents c2 &lt;span class="hl kwa"&gt;on&lt;/span&gt; c1.row_id &lt;span class="hl opt"&gt;=&lt;/span&gt; c2.row_id  &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
    c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;72039556&lt;/span&gt; |
 &lt;span class="hl num"&gt;39118376&lt;/span&gt; | abnormal
   &lt;span class="hl num"&gt;258288&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;234570.663&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;03&lt;/span&gt;&lt;span class="hl kwc"&gt;:54&lt;/span&gt;.571&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;insert into&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;select&lt;/span&gt; &lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT&lt;/span&gt; &lt;span class="hl num"&gt;0 55708110&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;1201961.089&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;20&lt;/span&gt;&lt;span class="hl kwc"&gt;:01&lt;/span&gt;.961&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
    c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;72039556&lt;/span&gt; |
 &lt;span class="hl num"&gt;39118376&lt;/span&gt; | abnormal
   &lt;span class="hl num"&gt;258288&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;7277.858&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;00&lt;/span&gt;&lt;span class="hl kwc"&gt;:07&lt;/span&gt;.278&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select&lt;/span&gt; c1.row_id&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;row_number&lt;/span&gt;&lt;span class="hl opt"&gt;()&lt;/span&gt; &lt;span class="hl kwa"&gt;over&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;partition by&lt;/span&gt; c1.itemid &lt;span class="hl kwa"&gt;order by&lt;/span&gt; c1.row_id &lt;span class="hl kwa"&gt;desc&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; rk &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
  row_id  | rk
&lt;span class="hl slc"&gt;----------+----&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;1&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;2&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;3&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;4&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;5&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;6&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;7&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;8&lt;/span&gt;
 &lt;span class="hl num"&gt;27906612&lt;/span&gt; |  &lt;span class="hl num"&gt;9&lt;/span&gt;
 &lt;span class="hl num"&gt;27906612&lt;/span&gt; | &lt;span class="hl num"&gt;10&lt;/span&gt;
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;465615.775&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;07&lt;/span&gt;&lt;span class="hl kwc"&gt;:45&lt;/span&gt;.616&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1 &lt;span class="hl kwa"&gt;join&lt;/span&gt; labevents c2 &lt;span class="hl kwa"&gt;on&lt;/span&gt; c1.row_id &lt;span class="hl opt"&gt;=&lt;/span&gt; c2.row_id  &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
     c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;-----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;288158224&lt;/span&gt; |
 &lt;span class="hl num"&gt;156473504&lt;/span&gt; | abnormal
   &lt;span class="hl num"&gt;1033152&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;494615.953&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;08&lt;/span&gt;&lt;span class="hl kwc"&gt;:14&lt;/span&gt;.616&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;delete from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;where&lt;/span&gt; row_id &lt;span class="hl opt"&gt;&amp;lt;&lt;/span&gt; &lt;span class="hl num"&gt;5000000&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;DELETE&lt;/span&gt; &lt;span class="hl num"&gt;19952316&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;157689.975&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;02&lt;/span&gt;&lt;span class="hl kwc"&gt;:37&lt;/span&gt;.690&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;update&lt;/span&gt;  labevents &lt;span class="hl kwa"&gt;set flag&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl sng"&gt;'new flag'&lt;/span&gt; &lt;span class="hl kwa"&gt;where&lt;/span&gt; row_id &lt;span class="hl opt"&gt;&amp;lt;&lt;/span&gt; &lt;span class="hl num"&gt;10000000&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;UPDATE&lt;/span&gt; &lt;span class="hl num"&gt;19949040&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;810058.857&lt;/span&gt; &lt;span class="hl kwd"&gt;ms&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;13&lt;/span&gt;&lt;span class="hl kwc"&gt;:30&lt;/span&gt;.059&lt;span class="hl opt"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;create unlogged table tbl_range (data1 text, data2 text, randomnumber double precision);
insert into tbl_range
( select
    ('{a,b,c,d,e,f}'::text[])[1 + floor(random() * 6)] as data1
    ,('{g,h,i,j,k,l}'::text[])[1 + floor(random() * 6)] as data2
    ,random() * 1000 as randomnumber
from generate_series(1,400000000));
SELECT madlib.pivot('tbl_range', 'pivout', 'data1', 'data2', 'randomnumber', 'sum,max');
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Greenplum&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;create table&lt;/span&gt; &lt;span class="hl kwd"&gt;labevents&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;
 row_id      &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt;subject_id  &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt;hadm_id     &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt;itemid      &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt;charttime   &lt;span class="hl kwa"&gt;timestamp&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;0&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; &lt;span class="hl kwa"&gt;without time zone&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl kwa"&gt;value&lt;/span&gt;       &lt;span class="hl kwb"&gt;character&lt;/span&gt; &lt;span class="hl kwa"&gt;varying&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;200&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt;valuenum    &lt;span class="hl kwa"&gt;double precision&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt;valueuom    &lt;span class="hl kwb"&gt;character&lt;/span&gt; &lt;span class="hl kwa"&gt;varying&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;20&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl kwa"&gt;flag&lt;/span&gt;        &lt;span class="hl kwb"&gt;character&lt;/span&gt; &lt;span class="hl kwa"&gt;varying&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;20&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;
 &lt;span class="hl opt"&gt;,&lt;/span&gt;mimic_id    &lt;span class="hl kwb"&gt;integer&lt;/span&gt;
 &lt;span class="hl opt"&gt;)&lt;/span&gt; &lt;span class="hl kwa"&gt;with&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;appendonly&lt;span class="hl opt"&gt;=&lt;/span&gt;&lt;span class="hl kwa"&gt;true&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; orientation&lt;span class="hl opt"&gt;=&lt;/span&gt;&lt;span class="hl kwa"&gt;column&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; compresstype&lt;span class="hl opt"&gt;=&lt;/span&gt;ZSTD &lt;span class="hl opt"&gt;);&lt;/span&gt;
NOTICE&lt;span class="hl opt"&gt;:&lt;/span&gt;  &lt;span class="hl kwa"&gt;Table&lt;/span&gt; doesn&lt;span class="hl sng"&gt;'t have '&lt;/span&gt;DISTRIBUTED &lt;span class="hl kwa"&gt;BY&lt;/span&gt;&lt;span class="hl sng"&gt;' clause -- Using column named '&lt;/span&gt;row_id&lt;span class="hl sng"&gt;' as the Greenplum Database data distribution key for this table.&lt;/span&gt;
&lt;span class="hl sng"&gt;HINT:  The '&lt;/span&gt;DISTRIBUTED &lt;span class="hl kwa"&gt;BY&lt;/span&gt;&lt;span class="hl sng"&gt;' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.&lt;/span&gt;
&lt;span class="hl sng"&gt;CREATE TABLE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# \&lt;span class="hl kwa"&gt;copy&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;from&lt;/span&gt; &lt;span class="hl sng"&gt;'/home/nparis/labevents.csv'&lt;/span&gt; &lt;span class="hl kwa"&gt;csv&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;COPY&lt;/span&gt; &lt;span class="hl num"&gt;27854055&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;80878&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;637&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
    c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;18009889&lt;/span&gt; |
  &lt;span class="hl num"&gt;9779594&lt;/span&gt; | abnormal
    &lt;span class="hl num"&gt;64572&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;1164&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;303&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select&lt;/span&gt; c1.row_id&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;row_number&lt;/span&gt;&lt;span class="hl opt"&gt;()&lt;/span&gt; &lt;span class="hl kwa"&gt;over&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;partition by&lt;/span&gt; c1.itemid &lt;span class="hl kwa"&gt;order by&lt;/span&gt; c1.row_id &lt;span class="hl kwa"&gt;desc&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; rk &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
  row_id  | rk
&lt;span class="hl slc"&gt;----------+----&lt;/span&gt;
 &lt;span class="hl num"&gt;27907576&lt;/span&gt; |  &lt;span class="hl num"&gt;1&lt;/span&gt;
 &lt;span class="hl num"&gt;27907382&lt;/span&gt; |  &lt;span class="hl num"&gt;2&lt;/span&gt;
 &lt;span class="hl num"&gt;27901097&lt;/span&gt; |  &lt;span class="hl num"&gt;3&lt;/span&gt;
 &lt;span class="hl num"&gt;27901054&lt;/span&gt; |  &lt;span class="hl num"&gt;4&lt;/span&gt;
 &lt;span class="hl num"&gt;27900783&lt;/span&gt; |  &lt;span class="hl num"&gt;5&lt;/span&gt;
 &lt;span class="hl num"&gt;27897288&lt;/span&gt; |  &lt;span class="hl num"&gt;6&lt;/span&gt;
 &lt;span class="hl num"&gt;27896669&lt;/span&gt; |  &lt;span class="hl num"&gt;7&lt;/span&gt;
 &lt;span class="hl num"&gt;27894567&lt;/span&gt; |  &lt;span class="hl num"&gt;8&lt;/span&gt;
 &lt;span class="hl num"&gt;27892281&lt;/span&gt; |  &lt;span class="hl num"&gt;9&lt;/span&gt;
 &lt;span class="hl num"&gt;27884982&lt;/span&gt; | &lt;span class="hl num"&gt;10&lt;/span&gt;
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;12569&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;391&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;insert into&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;select&lt;/span&gt; &lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT&lt;/span&gt; &lt;span class="hl num"&gt;0 27854055&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;79361&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;173&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
    c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;36019778&lt;/span&gt; |
 &lt;span class="hl num"&gt;19559188&lt;/span&gt; | abnormal
   &lt;span class="hl num"&gt;129144&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;2353&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;157&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select&lt;/span&gt; c1.row_id&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;row_number&lt;/span&gt;&lt;span class="hl opt"&gt;()&lt;/span&gt; &lt;span class="hl kwa"&gt;over&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;partition by&lt;/span&gt; c1.itemid &lt;span class="hl kwa"&gt;order by&lt;/span&gt; c1.row_id &lt;span class="hl kwa"&gt;desc&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; rk &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
  row_id  | rk
&lt;span class="hl slc"&gt;----------+----&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;1&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;2&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;3&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;4&lt;/span&gt;
 &lt;span class="hl num"&gt;27906612&lt;/span&gt; |  &lt;span class="hl num"&gt;5&lt;/span&gt;
 &lt;span class="hl num"&gt;27906612&lt;/span&gt; |  &lt;span class="hl num"&gt;6&lt;/span&gt;
 &lt;span class="hl num"&gt;27906561&lt;/span&gt; |  &lt;span class="hl num"&gt;7&lt;/span&gt;
 &lt;span class="hl num"&gt;27906561&lt;/span&gt; |  &lt;span class="hl num"&gt;8&lt;/span&gt;
 &lt;span class="hl num"&gt;27906550&lt;/span&gt; |  &lt;span class="hl num"&gt;9&lt;/span&gt;
 &lt;span class="hl num"&gt;27906550&lt;/span&gt; | &lt;span class="hl num"&gt;10&lt;/span&gt;
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;25409&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;642&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1 &lt;span class="hl kwa"&gt;join&lt;/span&gt; labevents c2 &lt;span class="hl kwa"&gt;on&lt;/span&gt; c1.row_id &lt;span class="hl opt"&gt;=&lt;/span&gt; c2.row_id  &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
    c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;72039556&lt;/span&gt; |
 &lt;span class="hl num"&gt;39118376&lt;/span&gt; | abnormal
   &lt;span class="hl num"&gt;258288&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;101654&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;716&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;insert into&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;select&lt;/span&gt; &lt;span class="hl opt"&gt;*&lt;/span&gt; &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;INSERT&lt;/span&gt; &lt;span class="hl num"&gt;0 55708110&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;112203&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;521&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
    c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;72039556&lt;/span&gt; |
 &lt;span class="hl num"&gt;39118376&lt;/span&gt; | abnormal
   &lt;span class="hl num"&gt;258288&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;3941&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;551&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select&lt;/span&gt; c1.row_id&lt;span class="hl opt"&gt;,&lt;/span&gt; &lt;span class="hl kwa"&gt;row_number&lt;/span&gt;&lt;span class="hl opt"&gt;()&lt;/span&gt; &lt;span class="hl kwa"&gt;over&lt;/span&gt;&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl kwa"&gt;partition by&lt;/span&gt; c1.itemid &lt;span class="hl kwa"&gt;order by&lt;/span&gt; c1.row_id &lt;span class="hl kwa"&gt;desc&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; rk &lt;span class="hl kwa"&gt;from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1   &lt;span class="hl kwa"&gt;limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
  row_id  | rk
&lt;span class="hl slc"&gt;----------+----&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;1&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;2&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;3&lt;/span&gt;
 &lt;span class="hl num"&gt;27906665&lt;/span&gt; |  &lt;span class="hl num"&gt;4&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;5&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;6&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;7&lt;/span&gt;
 &lt;span class="hl num"&gt;27906621&lt;/span&gt; |  &lt;span class="hl num"&gt;8&lt;/span&gt;
 &lt;span class="hl num"&gt;27906612&lt;/span&gt; |  &lt;span class="hl num"&gt;9&lt;/span&gt;
 &lt;span class="hl num"&gt;27906612&lt;/span&gt; | &lt;span class="hl num"&gt;10&lt;/span&gt;
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;65279&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;232&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;select count&lt;/span&gt;&lt;span class="hl opt"&gt;(*)&lt;/span&gt; c&lt;span class="hl opt"&gt;,&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;as&lt;/span&gt; c1 &lt;span class="hl kwa"&gt;join&lt;/span&gt; labevents c2 &lt;span class="hl kwa"&gt;on&lt;/span&gt; c1.row_id &lt;span class="hl opt"&gt;=&lt;/span&gt; c2.row_id  &lt;span class="hl kwa"&gt;group by&lt;/span&gt; c1.&lt;span class="hl kwa"&gt;flag order by&lt;/span&gt; c  &lt;span class="hl kwa"&gt;desc limit&lt;/span&gt; &lt;span class="hl num"&gt;10&lt;/span&gt; &lt;span class="hl opt"&gt;;&lt;/span&gt;
     c     |   &lt;span class="hl kwa"&gt;flag&lt;/span&gt;
&lt;span class="hl slc"&gt;-----------+----------&lt;/span&gt;
 &lt;span class="hl num"&gt;288158224&lt;/span&gt; |
 &lt;span class="hl num"&gt;156473504&lt;/span&gt; | abnormal
   &lt;span class="hl num"&gt;1033152&lt;/span&gt; | delta
&lt;span class="hl opt"&gt;(&lt;/span&gt;&lt;span class="hl num"&gt;3&lt;/span&gt; &lt;span class="hl kwa"&gt;rows&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt;

&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;188816&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;067&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;delete from&lt;/span&gt; labevents &lt;span class="hl kwa"&gt;where&lt;/span&gt; row_id &lt;span class="hl opt"&gt;&amp;lt;&lt;/span&gt; &lt;span class="hl num"&gt;5000000&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;DELETE&lt;/span&gt; &lt;span class="hl num"&gt;19952316&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;8930&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;371&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;update&lt;/span&gt;  labevents &lt;span class="hl kwa"&gt;set flag&lt;/span&gt; &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl sng"&gt;'new flag'&lt;/span&gt; &lt;span class="hl kwa"&gt;where&lt;/span&gt; row_id &lt;span class="hl opt"&gt;&amp;lt;&lt;/span&gt; &lt;span class="hl num"&gt;10000000&lt;/span&gt;&lt;span class="hl opt"&gt;;&lt;/span&gt;
&lt;span class="hl kwa"&gt;UPDATE&lt;/span&gt; &lt;span class="hl num"&gt;19949040&lt;/span&gt;
&lt;span class="hl kwa"&gt;Time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;32977&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl num"&gt;965&lt;/span&gt; ms
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;nparis@gnubuntu&lt;span class="hl opt"&gt;:&lt;/span&gt;~&lt;span class="hl opt"&gt;/&lt;/span&gt;bin$ &lt;span class="hl opt"&gt;/&lt;/span&gt;opt&lt;span class="hl opt"&gt;/&lt;/span&gt;greenplum&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl kwa"&gt;db&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;6&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;6.12.1&lt;/span&gt;&lt;span class="hl opt"&gt;/&lt;/span&gt;bin&lt;span class="hl opt"&gt;/&lt;/span&gt;gpload &lt;span class="hl opt"&gt;-&lt;/span&gt;f gpload.yaml
&lt;span class="hl num"&gt;2020&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;12&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;04 18&lt;/span&gt;&lt;span class="hl kwc"&gt;:16:38&lt;/span&gt;|INFO|gpload &lt;span class="hl kwa"&gt;session&lt;/span&gt; started &lt;span class="hl num"&gt;2020&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;12&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;04 18&lt;/span&gt;&lt;span class="hl kwc"&gt;:16:38&lt;/span&gt;
&lt;span class="hl num"&gt;2020&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;12&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;04 18&lt;/span&gt;&lt;span class="hl kwc"&gt;:16:38&lt;/span&gt;|INFO|started gpfdist &lt;span class="hl opt"&gt;-&lt;/span&gt;p &lt;span class="hl num"&gt;8081&lt;/span&gt; &lt;span class="hl opt"&gt;-&lt;/span&gt;P &lt;span class="hl num"&gt;8082&lt;/span&gt; &lt;span class="hl opt"&gt;-&lt;/span&gt;f &lt;span class="hl sng"&gt;"/home/nparis/labevents.csv"&lt;/span&gt; &lt;span class="hl opt"&gt;-&lt;/span&gt;t &lt;span class="hl num"&gt;30&lt;/span&gt;
&lt;span class="hl num"&gt;2020&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;12&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;04 18&lt;/span&gt;&lt;span class="hl kwc"&gt;:17:49&lt;/span&gt;|INFO|running &lt;span class="hl kwa"&gt;time&lt;/span&gt;&lt;span class="hl opt"&gt;:&lt;/span&gt; &lt;span class="hl num"&gt;71.18&lt;/span&gt; seconds
&lt;span class="hl num"&gt;2020&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;12&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;04 18&lt;/span&gt;&lt;span class="hl kwc"&gt;:17:49&lt;/span&gt;|INFO|&lt;span class="hl kwa"&gt;rows&lt;/span&gt; Inserted          &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl num"&gt;27854055&lt;/span&gt;
&lt;span class="hl num"&gt;2020&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;12&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;04 18&lt;/span&gt;&lt;span class="hl kwc"&gt;:17:49&lt;/span&gt;|INFO|&lt;span class="hl kwa"&gt;rows&lt;/span&gt; Updated           &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl num"&gt;0&lt;/span&gt;
&lt;span class="hl num"&gt;2020&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;12&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;04 18&lt;/span&gt;&lt;span class="hl kwc"&gt;:17:49&lt;/span&gt;|INFO|&lt;span class="hl kwa"&gt;data&lt;/span&gt; formatting errors &lt;span class="hl opt"&gt;=&lt;/span&gt; &lt;span class="hl num"&gt;0&lt;/span&gt;
&lt;span class="hl num"&gt;2020&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;12&lt;/span&gt;&lt;span class="hl opt"&gt;-&lt;/span&gt;&lt;span class="hl num"&gt;04 18&lt;/span&gt;&lt;span class="hl kwc"&gt;:17:49&lt;/span&gt;|INFO|gpload succeeded
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;warehouse&lt;span class="hl opt"&gt;=&lt;/span&gt;# &lt;span class="hl kwa"&gt;create table&lt;/span&gt; &lt;span class="hl kwd"&gt;tbl_range&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;data1 &lt;span class="hl kwb"&gt;text&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; data2 &lt;span class="hl kwb"&gt;text&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; randomnumber &lt;span class="hl kwa"&gt;double precision&lt;/span&gt;&lt;span class="hl opt"&gt;)&lt;/span&gt; &lt;span class="hl kwa"&gt;with&lt;/span&gt; &lt;span class="hl opt"&gt;(&lt;/span&gt;appendonly&lt;span class="hl opt"&gt;=&lt;/span&gt;&lt;span class="hl kwa"&gt;true&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; orientation&lt;span class="hl opt"&gt;=&lt;/span&gt;&lt;span class="hl kwa"&gt;column&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt; compresstype&lt;span class="hl opt"&gt;=&lt;/span&gt;ZLIB &lt;span class="hl opt"&gt;);&lt;/span&gt;
NOTICE&lt;span class="hl opt"&gt;:&lt;/span&gt;  &lt;span class="hl kwa"&gt;Table&lt;/span&gt; doesn&lt;span class="hl sng"&gt;'t have '&lt;/span&gt;DISTRIBUTED &lt;span class="hl kwa"&gt;BY&lt;/span&gt;&lt;span class="hl sng"&gt;' clause -- Using column named '&lt;/span&gt;data1&lt;span class="hl sng"&gt;' as the Greenplum Database data distribution key for this table.&lt;/span&gt;
&lt;span class="hl sng"&gt;HINT:  The '&lt;/span&gt;DISTRIBUTED &lt;span class="hl kwa"&gt;BY&lt;/span&gt;&lt;span class="hl sng"&gt;' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.&lt;/span&gt;
&lt;span class="hl sng"&gt;CREATE TABLE&lt;/span&gt;
&lt;span class="hl sng"&gt;Time: 352,343 ms&lt;/span&gt;
&lt;span class="hl sng"&gt;warehouse=#                                                                                                                                    insert into tbl_range&lt;/span&gt;
&lt;span class="hl sng"&gt;( select&lt;/span&gt;
&lt;span class="hl sng"&gt;    ('&lt;/span&gt;&lt;span class="hl opt"&gt;{&lt;/span&gt;a&lt;span class="hl opt"&gt;,&lt;/span&gt;b&lt;span class="hl opt"&gt;,&lt;/span&gt;c&lt;span class="hl opt"&gt;,&lt;/span&gt;d&lt;span class="hl opt"&gt;,&lt;/span&gt;e&lt;span class="hl opt"&gt;,&lt;/span&gt;f&lt;span class="hl opt"&gt;}&lt;/span&gt;&lt;span class="hl sng"&gt;'::text[])[1 + floor(random() * 6)] as data1&lt;/span&gt;
&lt;span class="hl sng"&gt;    ,('&lt;/span&gt;&lt;span class="hl opt"&gt;{&lt;/span&gt;g&lt;span class="hl opt"&gt;,&lt;/span&gt;h&lt;span class="hl opt"&gt;,&lt;/span&gt;i&lt;span class="hl opt"&gt;,&lt;/span&gt;j&lt;span class="hl opt"&gt;,&lt;/span&gt;k&lt;span class="hl opt"&gt;,&lt;/span&gt;l&lt;span class="hl opt"&gt;}&lt;/span&gt;&lt;span class="hl sng"&gt;'::text[])[1 + floor(random() * 6)] as data2&lt;/span&gt;
&lt;span class="hl sng"&gt;    ,random() * 1000 as randomnumber&lt;/span&gt;
&lt;span class="hl sng"&gt;from generate_series(1,100000000)) ;&lt;/span&gt;
&lt;span class="hl sng"&gt;INSERT 0 100000000&lt;/span&gt;
&lt;span class="hl sng"&gt;Time: 145408,190 ms&lt;/span&gt;
&lt;span class="hl sng"&gt;warehouse=# SELECT madlib.pivot('&lt;/span&gt;tbl_range&lt;span class="hl sng"&gt;', '&lt;/span&gt;pivout&lt;span class="hl sng"&gt;', '&lt;/span&gt;data1&lt;span class="hl sng"&gt;', '&lt;/span&gt;data2&lt;span class="hl sng"&gt;', '&lt;/span&gt;randomnumber&lt;span class="hl sng"&gt;', '&lt;/span&gt;&lt;span class="hl kwa"&gt;sum&lt;/span&gt;&lt;span class="hl opt"&gt;,&lt;/span&gt;&lt;span class="hl kwa"&gt;max&lt;/span&gt;&lt;span class="hl sng"&gt;');&lt;/span&gt;
&lt;span class="hl sng"&gt; pivot&lt;/span&gt;
&lt;span class="hl sng"&gt;-------&lt;/span&gt;
&lt;span class="hl sng"&gt;&lt;/span&gt;
&lt;span class="hl sng"&gt;(1 row)&lt;/span&gt;
&lt;span class="hl sng"&gt;&lt;/span&gt;
&lt;span class="hl sng"&gt;Time: 67074,359 ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;create table tbl_range (data1 text, data2 text, randomnumber double precision) with (appendonly=true, orientation=column, compresstype=ZLIB );
insert into tbl_range
( select
    ('{a,b,c,d,e,f}'::text[])[1 + floor(random() * 6)] as data1
    ,('{g,h,i,j,k,l}'::text[])[1 + floor(random() * 6)] as data2
    ,random() * 1000 as randomnumber
from generate_series(1,400000000));
SELECT madlib.pivot('tbl_range', 'pivout', 'data1', 'data2', 'randomnumber', 'sum,max');
&lt;/code&gt;&lt;/pre&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Postgresql Versus Greenplum — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-11-07 11:53&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/postgresql-versus-greenplum" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/an-archeology-mobile-application</id>
    <title>An archeology mobile application</title>
    <updated>2021-03-28T22:16:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;div id="generated-toc"&gt; &lt;/div&gt;
&lt;p&gt;&lt;span&gt;Published on &lt;time id="post-date"&gt;2021-03-28&lt;/time&gt;&lt;/span&gt;
&lt;span id="reading-time" style="visibility:hidden;"&gt;less than a minute&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;An archeology mobile application&lt;/h1&gt;
&lt;h2&gt;There is a tool I need&lt;/h2&gt;
&lt;p&gt;I regularly find ancient artefacts (mostly prehistoric silex). I would
find highly valuable to store the GPS coordinate of those, and get a
map.&lt;/p&gt;
&lt;p&gt;I know this practice is subject to regulation. However, most of the
time, I found the stuff in ploughed fields or in the forest trails. My
guess is having the tool to store and share the information could help
the research by building an open-database.&lt;/p&gt;
&lt;p&gt;Such a tool could be free software, accesible to anybody. Some feature
will allow collaboration (annotation) and also contact between
users. The dataset (including photos) will be released as open-data.&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;create an account&lt;/li&gt;
&lt;li&gt;upload a geologalized photo&lt;/li&gt;
&lt;li&gt;show artifacts on a map
&lt;ul&gt;
&lt;li&gt;filter by category&lt;/li&gt;
&lt;li&gt;filter by user&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;add metadata&lt;/li&gt;
&lt;li&gt;suggest metadata&lt;/li&gt;
&lt;li&gt;export open-data&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Implemention&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;python API (fastapi)&lt;/li&gt;
&lt;li&gt;postgresql database, postgis&lt;/li&gt;
&lt;li&gt;object storage (store the images)&lt;/li&gt;
&lt;li&gt;imagemagic tools&lt;/li&gt;
&lt;li&gt;android client application&lt;/li&gt;
&lt;li&gt;website client application&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=An archeology mobile application — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-03-28 22:16&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/an-archeology-mobile-application" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/self-hosted-mail</id>
    <title>Self hosting emails in the 21th centory</title>
    <updated>2021-06-13T16:43:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;div id="generated-toc"&gt; &lt;/div&gt;
&lt;p&gt;&lt;span&gt;Published on &lt;time id="post-date"&gt;2021-06-13&lt;/time&gt;&lt;/span&gt;
&lt;span id="reading-time" style="visibility:hidden;"&gt;2 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;Self hosting emails in the 21th centory&lt;/h1&gt;
&lt;h2&gt;Why self hosting emails&lt;/h2&gt;
&lt;p&gt;Mailing technology still active after decades of production. It's one
of the simpliest and universal way of sharing information. There is
out there a lot of very efficient solutions such gmail or
protonmail.&lt;/p&gt;
&lt;p&gt;But mail is FUN with a very broad spectrum of technology to
master. For example, mailu is built over containers and targets
kubernetes, it has a flask api/cli, is maintained by a prolific
community using great automation tools on the continuous delivery and
also bots on matrix. It has a machine learning based spam filter.&lt;/p&gt;
&lt;p&gt;Also mail is serious with personal informations, that shall be kept
secret. Hacking ofter takes place on the mailing area, and
understanding how this stuff works is a great skill.&lt;/p&gt;
&lt;h2&gt;Available mailing selfhosted solutions&lt;/h2&gt;
&lt;p&gt;Mail In A Box (aka MIAB) looks the most advanced solution.&lt;/p&gt;
&lt;p&gt;Mailu is quite new and it naturally comes with less features. One
major distinction compared to MIAB is its configurability. Most of the
modules are optional or sereval choices availables.&lt;/p&gt;
&lt;h2&gt;Ham &amp;amp; Spam&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;smtp port 25&lt;/code&gt; shall be opened. However most internet box close it
by defaul. It is often possible to open it from the box web ui.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;reverse dns&lt;/code&gt;is a huge obstacle to self host email. The domain
name associated with the home ip server has to be the same as the mail
domain name. Sadly most internet providers does not allow clients to
change the value of rDNS (which is trivial on the cloud).&lt;/p&gt;
&lt;h2&gt;Using a relay&lt;/h2&gt;
&lt;p&gt;Because sending trusted email from a home server is so tricky one can
use a mail provider (such riseup) to deliver the email. Also the
provider can route the email to your selfhosted server. In this case,
you still use your existing email, but nothing is stored on the
provider side but on your own instance.&lt;/p&gt;
&lt;p&gt;The main advantage with this is you manage your storage yourself. Also
in term of privacy, your provider does not store your email
history. By the way the email only transit on his side.&lt;/p&gt;
&lt;h2&gt;Email client&lt;/h2&gt;
&lt;p&gt;I have been using in the past multiple cli email clients such &lt;code&gt;mutt&lt;/code&gt;,
&lt;code&gt;neomutt&lt;/code&gt; and &lt;code&gt;mu4e&lt;/code&gt; together with local indexing tools such &lt;code&gt;notmuch&lt;/code&gt;
or &lt;code&gt;mu&lt;/code&gt;. Those tools are not designed to work with imap but with
pop. This means the emails are pulled locally and indexed.&lt;/p&gt;
&lt;p&gt;Having a self-hosted email solution such &lt;code&gt;mailu&lt;/code&gt; or &lt;code&gt;mail in a box&lt;/code&gt;
let use the dovecot full text searching feature based on xapian or
solr. Together with the imap protocol, it leverages server search with
great performances. Moreover imap is far better than pop because all
your client will have the same view on the maildir, and there is no
need to store locally the emails which improves security.&lt;/p&gt;
&lt;p&gt;In the terminal, &lt;code&gt;aerc&lt;/code&gt; is a great cli email client focused on imap
and it supports server side FTS (&lt;code&gt;filter -a&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;On desktop, evolution also is a great software, and it provides imap
push in order to get real time notifications and decrease server load.&lt;/p&gt;
&lt;p&gt;On mobile, &lt;code&gt;k9mail&lt;/code&gt; is great, and provides draft email encryption,
autocrypt. Sadly the FTS is not yet supported. I would be glad to help
on this. I have also tested fairemail, but most interesting features
are limited to the paid version.&lt;/p&gt;
&lt;h2&gt;Calendar, contacts and tasks&lt;/h2&gt;
&lt;p&gt;Having our contacts and calendar together with the email is
important. Mailu provides a simple python package &lt;code&gt;radicale&lt;/code&gt; which
brings this features. It does not come with a visual calendar, but can
export vcal and ics formats. Mobile applications such &lt;code&gt;etar calendar&lt;/code&gt;,
&lt;code&gt;tasks&lt;/code&gt;, can connect to radicale and synchronize content thought &lt;code&gt;davx5&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Mail-in-a-box comes with next-cloud calendar which is a more complete
solution but too heavy for my taste.&lt;/p&gt;
&lt;p&gt;Roundcube webmail is able to connect to radicale carddav feature
only. Sadly it does not provide any decent calendar plugin.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Self hosting emails in the 21th centory — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-06-13 16:43&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/self-hosted-mail" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/python-coding-env</id>
    <title>Relax with python</title>
    <updated>2021-08-18T22:32:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;div id="generated-toc"&gt; &lt;/div&gt;
&lt;p&gt;&lt;span&gt;Published on &lt;time id="post-date"&gt;2021-07-15&lt;/time&gt;&lt;/span&gt;
&lt;span id="reading-time" style="visibility:hidden;"&gt;2 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;Relax with python&lt;/h1&gt;
&lt;p&gt;Most programmer knows python and like it. I have been working with it
a lot recently, and there is few important caveat to really have good
time.&lt;/p&gt;
&lt;h2&gt;Forget vim or emacs: Use a tool called an IDE&lt;/h2&gt;
&lt;p&gt;I have much affection for both vim and emacs and being currently
writing this post with the latter. I tried my best to setup a full
fledged python with it and I won't do it again. I lost myself in few
tutorials and when in the end I got a result it was far from the
feature a python IDE can offer.&lt;/p&gt;
&lt;p&gt;Intellij IDE has a python plugin which turn it into Pycharm. Unlike
vim and emacs, they parse the python code with an AST, which provide
some powerful feature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a powerful python debugger !&lt;/li&gt;
&lt;li&gt;find where is used the given object in the project&lt;/li&gt;
&lt;li&gt;batch rename object in the project&lt;/li&gt;
&lt;li&gt;refactor piece of code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It also come with feature we like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an authentic vim key binding, including search/replace, tab navigation&lt;/li&gt;
&lt;li&gt;an integrated git manager (as good as magit for emacs)&lt;/li&gt;
&lt;li&gt;search for files and search within files&lt;/li&gt;
&lt;li&gt;a nice dark mode&lt;/li&gt;
&lt;li&gt;pytest integration&lt;/li&gt;
&lt;li&gt;last but not least, it manages most programming languages out of the box&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Manage your python versions with pyenv&lt;/h2&gt;
&lt;p&gt;Managing multiple versions of python is not trivial, and there is many
ways for this. You can go with the packaged versions of the OS (such
apt), but it won't have new versions and you will end up adding weird
source list and repository. I did use anaconda which is a huge
reptilian mess.&lt;/p&gt;
&lt;p&gt;Pyenv is really the silver bullet for this. What it does is provide a
command line for installing (download and compile) every python
version that exist including minors and beta. You can then choose for
each project the one you want, without ANY friction. Pyenv is not a
replacement with virtualenv at all, they actually combine: you build
venv with a given python version provided by pyenv.&lt;/p&gt;
&lt;h2&gt;Manage you project environment with direnv&lt;/h2&gt;
&lt;p&gt;Python is so popular, you end up with many
virtualenv. Activating/deactivating them becomes really painful. And
you will forget to do so, and compromise your pip environment easily.&lt;/p&gt;
&lt;p&gt;direnv automates the management of virtualenvs when you navigate in
the linux projects, it activate / deactivate them accordingly. You
never have to do this again.&lt;/p&gt;
&lt;p&gt;It has a pyenv binding and it's super easy to specify the python
version you d'like in your venv. This produce a virtualenv folder
called .direnv at the root of your project. In order to make intellij
not considering this folder's python sources as part of the project,
you simply have to "exclude" it with a right click.&lt;/p&gt;
&lt;h2&gt;Format your code with black&lt;/h2&gt;
&lt;p&gt;Python syntax rules are great, but it is not perfect. There is still
freedom in the way every one format there code. Black takes care of
everything. Its main advantage is it formats the same source code the
same way, independently of how it is formatted at the beginning.&lt;/p&gt;
&lt;h2&gt;Commit your code with pre-commit&lt;/h2&gt;
&lt;p&gt;There is many small details that everyone wants: format python,
markdown, xml, yaml... All this can be added BEFORE committing to git
with a git-hook. pre-commit takes care of all, and let you add those
step within a descriptive configuration.&lt;/p&gt;
&lt;h2&gt;Test your code with tox&lt;/h2&gt;
&lt;p&gt;When you test the code you don't only check the source code acts
correctly, you also test its environment works. Tox encapsulates the
tests in order they will work on your computer but also on the other's
one. With tox, you avoid the "it works on my laptop" syndrome.&lt;/p&gt;
&lt;h2&gt;Build your changelog with Towncrier&lt;/h2&gt;
&lt;p&gt;Maintaining a changelog is important and there is several tools out
there. Towncrier simplifies this process, and with few efforts, you
get a clear and maintained changelog.md file.&lt;/p&gt;
&lt;h2&gt;Publish your package on pypi with twine&lt;/h2&gt;
&lt;p&gt;Publishing on pypi can be straightforward when you use the right
tools. Both setuptools and twine are fine for this. You also have to
get several files present. &lt;a href="https://pgjones.dev/blog/packaging-without-setup-py-2020"&gt;This
blog&lt;/a&gt; is
helpful for this.&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Relax with python — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-08-18 22:32&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/python-coding-env" rel="alternate"/>
  </entry>
  <entry>
    <id>https://blog.parisni.com/blog/demenagement</id>
    <title>Aujourd'hui: je déménage demain</title>
    <updated>2021-12-01T23:43:00+00:00</updated>
    <content type="html">&lt;div id="generated-toc"&gt; &lt;/div&gt;&lt;hr&gt; &lt;div id="generated-toc"&gt; &lt;/div&gt;
&lt;p&gt;&lt;span&gt;Published on &lt;time id="post-date"&gt;2021-11-25&lt;/time&gt;&lt;/span&gt;
&lt;span id="reading-time" style="visibility:hidden;"&gt;6 minutes&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;Aujourd'hui: je déménage demain&lt;/h1&gt;
&lt;p&gt;Je déménage dans 3 mois, disons sur la planete Mars. Dans ce billet, je biffe les sociétés
en question, appelons les:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FRIC: Une société fournissant téléphonie et internet&lt;/li&gt;
&lt;li&gt;CPAFER: Une société fournissant téléphonie et internet, mais aussi
l'infrastructure réseau&lt;/li&gt;
&lt;li&gt;Abrasif: Une société revendant de la téléphonie et internet pour le compte de
FRIC et CPAFER&lt;/li&gt;
&lt;li&gt;SUM: Une société fournissant électricité&lt;/li&gt;
&lt;li&gt;OEUF-DES-HAIES: Une société fournissant électricité&lt;/li&gt;
&lt;li&gt;CanalPlouf: Une société de télévision&lt;/li&gt;
&lt;li&gt;Clitoriche: Une société fournissant téléphonie et internet, partenaire de CanalPlouf&lt;/li&gt;
&lt;li&gt;Le service des Empotés: Une administration responsable de la récolte des
finances&lt;/li&gt;
&lt;li&gt;PapierQ: Cette société m'a été conseillée par l'agence immobilière, et se
présente comme un organisme financé par des acteurs divers, pour simplifier
les aspects administratifs des déménagements, en particulier l'energie,
l'internet et la téléphonie. De plus, ils ont des contrats avec des offres
exclusives&lt;/li&gt;
&lt;li&gt;STOP-DIRECT: Mon ancienne banque: j'ai dû en changer pour obtenir un prêt
immobilier ailleurs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans cette aventure, je cherche à me doter d'internet, du téléphone fixe, et de
l'electricité de manière optimale. En quête secondaire, je tente de changer de
banque sans faire de vagues.&lt;/p&gt;
&lt;h2&gt;JOUR 1&lt;/h2&gt;
&lt;h3&gt;Clitoriche&lt;/h3&gt;
&lt;p&gt;Le site internet de la planete Mars donne des détails sur la mise en place de la
fibre dans la ville ou j'emmenage dans 3 mois. Je commence par signaler au
webmaster un lien mort qui m'empeche de confirmer par moi même l'eligibilté de
mon domicile. Je vois cependant le contact de Clitoriche, société mettant en
œuvre la fibre dans ma ville.&lt;/p&gt;
&lt;p&gt;Je les contacte donc avec pour objectif de vérifier mon éligibilité. J'indique
habiter dans un immeuble au numéro 666. La personne me répond que le logement ne
contient qu'un seul habitant et que cela doit être une erreur dans leur
fichier, et qu'une demande de rectification doit être faite avant de souscrire.
Je me frotte les mains avec le sentiment de gagner du temps en évitant des
complications à m'y prendre à l'avance.&lt;/p&gt;
&lt;h2&gt;JOUR 2&lt;/h2&gt;
&lt;h3&gt;Clitoriche&lt;/h3&gt;
&lt;p&gt;Entre temps, en feuilletant les papiers OEUF-DES-HAIES, je réalise que j'habite au 666B.
Pour éviter d'engager une procédure inutile, je rapelle Clitoriche pour leur
signifier mon erreur. Après avoir expliqué le contexte, la personne au bout du
fil me demande mon code de souscription que j'ai dû recevoir par mail. Je suis
formel: je n'ai pas reçu de mail. Pour retrouver mon dossier, je donne mon
adresse email. Il ne lui est pas possible de changer mon addresse pour le 666B.
La personne me conseille alors de rappeler, et de demander le service de
souscription pour résilier mon compte en fournissant mon code.  Je lui fais
remarquer que je n'ai justement pas ce code. La personne me demande de
patienter. Après 10 minutes d'attente, la ligne est coupée.&lt;/p&gt;
&lt;p&gt;Je rappelle donc Clitoriche avec une stratégie différente: je demande à
souscrire un nouveau contrat.  Je vais donc au bout de la démarche en précisant
le 666B cette fois, et je reçois enfin l'email, avec le code. C'est un forfait
fibre à 33€/mois, sans télévision, avec une téléphonie payante à la minute pour
les appels sortants: ce n'est pas donné mais après tout, ce sont les seuls à
fournir de la fibre ?&lt;/p&gt;
&lt;p&gt;Je ne réalise pas à ce moment là que je ne souhaitais pas prendre de contrat si
tôt mais simplement vérifier mon éligibilité à la fibre.&lt;/p&gt;
&lt;h3&gt;PapierQ&lt;/h3&gt;
&lt;p&gt;Avec un sentiment d'accomplissement, j'enchaine avec PapierQ.&lt;/p&gt;
&lt;p&gt;Je souhaite gérer l'electricité avec eux. Très cordial, mon interlocuteur me
conseille de prendre un contrat à taux fixe au plus vite étant donné
l'augmentation du prix de l'energie dûe à la crise du gaz avec les Russes. Il
me fait l'éloge de SUM énergie, et sa filiale Verte. Je refrenne mon envie de
tempérer son engouement vis à vis de SUM, et nous passons à la simulation.
Après vérification, le verdict tombe: le forfait que SUM me propose est de
160€ par mois. Je tombe de si haut, que je ne ressens rien tant le choc est
violent et sec. Nous tombons d'accord pour considérer une autre option, à
savoir payer en fonction de ce qui est consommé. Cela est plus raisonnable, 9€
pour le forfait, 5€ pour l'assurance 24/24 panne électrique, et le
kilowat/heure utilisé. Plutôt enjoué par la tournure des évenements, je lui
demande néammoins si l'assurance est optionnelle, ce qu'il me confirme avec une
comme une gène dans la voix. Je ne me gène pas pour lui dire que j'aimerais
autant ne pas prendre cette assurance.&lt;/p&gt;
&lt;p&gt;Avant de se séparer bons amis, il me fait remarquer qu'il peut aussi me faire
une comparaison qui n'engage à rien sur les offres internet. Je suis déjà
engagé avec Clitoriche, mais finalement, pourquoi ne pas bénéficier de leurs bons
conseils voire de leurs offres spéciales ?&lt;/p&gt;
&lt;p&gt;Lui n'est pas habilité sur la partie internet et il me passe son collègue pour
lequel il a une estime et une confiance sans borne. Rapidement celui-ci
m'oriente vers FRIC. Après plusieurs confirmations de sa part: au 666B, je suis
bien éligible. Il m'annonce que le forfait disponible est a 20€/mois pendant
1an puis 44€ - mais que je pourrai changer - avec plus de 200 chaines de télé
et la téléphonie complète. Je lui fais part de mon désintéret pour la télé,
mais il n'a pas d'autre forfait à me proposer. Fort bien, cela me fait tout de
même gagner près de 14€ par mois par rapport à Clitoriche. C'est une belle
victoire, et je me réjouis d'annoncer mes prouesses à ma femme quand elle
va rentrer.&lt;/p&gt;
&lt;p&gt;Après avoir reçu de moi des explications liriques mais confuses et quelques
recherches de son côté, mon épouse me fait remarquer qu'un forfait FRIC semble
plus adapté et surtout moins cher que ce que j'ai souscrit. Immédiatement,
j'envoie un mail mesuré à PapierQ pour leur indiquer qu'un forfait plus
interessant que ce qu'ils m'ont fait souscrire semble exister, et que je leur
serais gré de me basculer dessus.&lt;/p&gt;
&lt;h2&gt;JOUR 3&lt;/h2&gt;
&lt;h3&gt;Empotés&lt;/h3&gt;
&lt;p&gt;Je reçois un email de mon ancienne banque STOP-DIRECT qui m'indique que mon
solde est désormais de 0€ et que tout à été envoyé à ma nouvelle banque. Je
suis étonné car le courrier que j'avais reçu quelques jours avant m'indiquait
que je devais leur envoyer un RIB et des justificatifs pour qu'ils procèdent à
ce transfert.  Mais soit, ce qui m'inquiète davantage est ma taxe d'habitation,
qui devait être débitée sur mon ancien compte. Ce n'est pas par choix, j'avais
fait le changement de coordonnées banquaires sur le site du service des
empotés, mais apparement cela n'a pas été pris en compte. Je tente donc de me
connecter aus site de STOP-DIRECT, mais mon compte à été gelé. Au téléphone, le
conseiller m'indique qu'en effet, un débit du service des Empotés est en cours
mais que celui-ci sera refusé, et que cela n'est pas aussi grâve que si il ne
pouvait pas être honoré.&lt;/p&gt;
&lt;p&gt;Sur le site du service des Empotés, je cherche par tous les diables la manière
de changer de coordonnées banquaires, et je finis par constater que la prise en
compte des nouveau RIB se fait au moins un mois après son changement.  Je les
contacte pour 1.  me plaindre du fait de ne pas avoir été prévenu au moment de
changer de RIB de la lenteur de ce processus et 2. leur demander comment
procéder pour que le prélèvement soit effectué sur ma nouvelle banque.&lt;/p&gt;
&lt;p&gt;Joie: je reçois une réponse dans la journée ! Je me rends sur le site pour
consulter ma messagerie sécurisée. En quelques mots laconiques on me confirme
"qu'en effet le changement de RIB prend un certain temps". Je dois me
concentrer avec énergie pour prendre la sage décision de poliement reformuler
ma question pour cette fois obtenir la marche à suivre pour qu'ils soient
payés, et que je ne devienne pas interdit banquaire.&lt;/p&gt;
&lt;h3&gt;PapierQ&lt;/h3&gt;
&lt;p&gt;Je reçois comme réponse que trop tard, si je veux changer de forfait, je dois
appeler un numéros FRIC (pour la modique somme de 0.35€/min).&lt;/p&gt;
&lt;h2&gt;JOUR 5&lt;/h2&gt;
&lt;h3&gt;Clitoriche&lt;/h3&gt;
&lt;p&gt;Comme prévu, je contacte Clitoriche avec cette fois, mon numéros de souscription.
Je reçois d'abord des excuses car leurs techniciens on indiqué un problème
sur mon dossier. J'en viens à expliquer mes problèmes à savoir que 1.
l'option téléphone n'est pas suffisante 2. j'ai vu un contrat 40% moins cher
chez eux et 3. je souhaite débuter mes mensualités dans 3 mois.&lt;/p&gt;
&lt;p&gt;Concernant l'option téléphone, si je débourse 5€ supplémentaires je pourrai
téléphoner sur les fixes en illimité. Si je débourse 4€ de plus par mois, c'est
aussi vers les mobiles que pourrais appeler sans limite. Cela nous s'élève
désormais à près de 45€/mois.&lt;/p&gt;
&lt;p&gt;Concernant le contrat moins cher, j'ai précisé que c'est sur "le réseau CPAFER"
que cette offre s'appuie. En entendant le mot clé CPAFER, mon interlocuteur ne
cache plus sa gène et m'indique que Clitoriche n'est pas CPAFER mais une filiale de
CanalPlouf. Je précise que l'offre est visible en première page sur leur site.
Après vérification, je dois noter le numéro de Clitoriche-CPAFER, une autre filiale.&lt;/p&gt;
&lt;p&gt;Concernant la question du début de mes mensualités, on me répond qu'il faut
attendre que mon compte soit débloqué, je pourrai les rappeler pour
avoir des détails. Je fais remarquer que c'est une question générale mais je
réalise que cette considération abstraite n'est pas à la porté de mon
interlocuteur, et je le remercie pour ses réponses précises.&lt;/p&gt;
&lt;p&gt;Le site que j'ai sous les yeux propose une simulation d'éligibilité à la fibre.
Je tente ma chance et je vois que je suis éligible à Bouygues, FRIC et une
vente privée, chacun avec un numéro de téléphone. Je décroche mon téléphone
pour appeler le numéro indiquant FRIC. La messagerie automatique m'indique que
je suis sur le service: Abrasif. Un conseiller me répond, je commence par lui
faire part de mon désarois: je pensais appeler FRIC. On me répond qu'Abrasif est
affiliée à FRIC. J'explique mon déménagement, ma prochaine addresse. La
personne vérifie mon éligibilité et le verdicte tombe: Je ne suis pas éligible
à la fibre, encore moins celle de FRIC.&lt;/p&gt;
&lt;h3&gt;Le service des Empotés&lt;/h3&gt;
&lt;p&gt;Je suis notifié par mail qu'une réponse du service des Empotés m'a été faite.
Une ligne laconique m'indique en substance que je peux leur envoyer un chèque.
Cette réponse déclenche une série de questions: quel chéquier (je ne l'ai pas
encore reçu), quelle addresse, quel ordre, quelle guarantie que mon nouveau RIB
ne va pas être prélevé aussi ? Je pense que cette conversation ne fait que
commencer.&lt;/p&gt;
&lt;h3&gt;FRIC&lt;/h3&gt;
&lt;p&gt;Après avoir reçu un mail et un sms de FRIC m'engageant à prendre rendez-vous
avec un technicien pour l'installation de ma ligne, je décide de consulter mon
espace client sur le site internet. À nouveau, je constate que le processus est
figé à la première étape : vérification de l'éligibilité.&lt;/p&gt;
&lt;p&gt;J'envisage alors de téléphoner à FRIC au numéro présent dans le mail: le 4242.
Très méfiant lorsque je lis "Gratuit depuis une ligne FRIC", je vérifie sur
plusieurs sites, et je suis convaincu: ce numéro est au prix d'un appel local,
c'est à dire gratuit dans le cadre de mon forfait mobile. En revanche, je
risque d'attendre très longtemps.&lt;/p&gt;
&lt;p&gt;La messagerie m'indique mon numéro de client (déduit de mon numéros de mobile).
Un conseiller me répond instantanément. Je lui indique que 1. je me suis trompé
d'offre 2. j'ai un doute sur mon éligibilité fibre et 3. j'aimerais débuter mes
mensualités dans 3 mois.&lt;/p&gt;
&lt;p&gt;Concernant mon offre, étant donné que rien n'a été déclenché de leur côté, il
me conseille de me rétracter et pour m'éviter d'avoir à rédiger une lettre, me
propose de le faire de son côté: voilà, c'est fait.&lt;/p&gt;
&lt;p&gt;Pour l'éligibilité à la fibre, il vérifie et me confirme que c'est le cas. Je
lui fais part de ma réserve étant donné que le réseau CPAFER n'est pas présent, il
m'explique qu'il s'agit d'un autre réseau: planete Mars fibre qui est associatif,
probablement mis en œuvre par la région. En outre, il m'indique que l'immeuble
d'à côté, le 666B ne l'est pas. Je réalise que le conseiller PapierQ m'a
inscrit par erreur au 666 avec FRIC, et je lui fais part qu'il est probable que
j'habite au 666B. Il me donne un détail sur le 666 qui compte 3 habitant: cela me
conforte dans l'idée que j'habite finalement au 666 et que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;l'adresse sur le contrat d'electricité est éronné (ce n'est pas le 666B)&lt;/li&gt;
&lt;li&gt;Clitoriche n'a pas le bon nombre d'habitant au 666&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;À suivre...&lt;/p&gt;
&lt;div id="last-modified"&gt;&lt;p&gt; &lt;a href="mailto:parisni@riseup.net?subject=Aujourd'hui: je déménage demain — software lobotomy"&gt;React ?&lt;/a&gt; &lt;/p&gt;This page was last modified:
    &lt;time id="git-timestamp"&gt; 2021-12-01 23:43&lt;/time&gt; &lt;/div&gt;</content>
    <link href="https://blog.parisni.com/blog/demenagement" rel="alternate"/>
  </entry>
</feed>

