<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Typo Blog</title>
        <link>https://typo.oyvindberg.dev/blog/</link>
        <description>Typo Blog</description>
        <lastBuildDate>Sun, 17 Dec 2023 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[The compilation cost of implicits]]></title>
            <link>https://typo.oyvindberg.dev/blog/the-cost-of-implicits/</link>
            <guid>https://typo.oyvindberg.dev/blog/the-cost-of-implicits/</guid>
            <pubDate>Sun, 17 Dec 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The compilation cost of implicits]]></description>
            <content:encoded><![CDATA[<p>I've accidentally built a compilation benchmark harness for Scala 2 and 3 which can measure the cost (in compilation time)
for having a codebase full of implicits which need to be resolved. Read on to see the results!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="background">Background<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background">​</a></h2>
<p>Typo is a code-generation library for working with PostgreSQL in Scala.
You can read more in the <a href="https://oyvindberg.github.io/typo/docs/" target="_blank" rel="noopener noreferrer">introduction</a>.</p>
<p>It was built to replace huge swathes of boilerplate in applications,
as well as to provide sorely needed type-safety to avoid having to test everything.</p>
<p>A crucial design goal was to fit into your system such as it is.
This means it generates code in the shared subset between Scala 2.12, 2.13 and 3.x,
and for three different database access libraries.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="typo-output-as-a-realistic-compile-speed-test-harness">Typo output as a realistic compile speed test harness<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#typo-output-as-a-realistic-compile-speed-test-harness" class="hash-link" aria-label="Direct link to Typo output as a realistic compile speed test harness" title="Direct link to Typo output as a realistic compile speed test harness">​</a></h3>
<p>In typical systems you may have a database layer, a business logic layer and a web layer,
with each of them occupying about a third of the code base.</p>
<p>The structure of the database and web layers are often very similar -
basically a bunch of case classes with type class instances and mapping code.</p>
<p>So let's say we take the database third of a typical system.
We'll use the fact that Typo can generate it in its entirety to build a compile speed benchmark,
where we contrast different combinations of scala versions and database libraries.</p>
<p>I'll stress that the code it generates is basically the same code I've written again and again over the years,
which should make the benchmark interesting since this is so close to real-world application code.</p>
<p>Let's see where it takes us!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-generated-code">The generated code<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#the-generated-code" class="hash-link" aria-label="Direct link to The generated code" title="Direct link to The generated code">​</a></h2>
<p>If you're curious about the generated code,
you can expand this section to see some example code
for an email address table in the <a href="https://github.com/lorint/AdventureWorks-for-Postgres" target="_blank" rel="noopener noreferrer">AdventureWorks database</a>,
generated for doobie.</p>
<!-- -->
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>EmailaddressId.scala</summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/</span><span class="token important">**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * File has been automatically generated by `typo`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package adventureworks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package person</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package emailaddress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.person.businessentity.BusinessentityId</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">/</span><span class="token important">**</span><span class="token plain"> Type for the composite primary key of table `person.emailaddress` </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">case class EmailaddressId(businessentityid</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> BusinessentityId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">emailaddressid</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Int)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">object EmailaddressId </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">implicit lazy val ordering</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Ordering</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressId</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = Ordering.by(x =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> (x.businessentityid</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> x.emailaddressid))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>EmailaddressRepo.scala</summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/</span><span class="token important">**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * File has been automatically generated by `typo`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package adventureworks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package person</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package emailaddress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import doobie.free.connection.ConnectionIO</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import fs2.Stream</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.DeleteBuilder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.SelectBuilder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.UpdateBuilder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">trait EmailaddressRepo </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def delete(compositeId</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressId)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Boolean</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def delete</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DeleteBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def insert(unsaved</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRow)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def insert(unsaved</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRowUnsaved)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def select</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> SelectBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def selectAll</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Stream</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ConnectionIO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def selectById(compositeId</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressId)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Option</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def update(row</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRow)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Boolean</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def update</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> UpdateBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def upsert(unsaved</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRow)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>EmailaddressRepoImpl.scala</summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/</span><span class="token important">**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * File has been automatically generated by `typo`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package adventureworks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package person</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package emailaddress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.customtypes.Defaulted</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.customtypes.TypoLocalDateTime</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.customtypes.TypoUUID</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import doobie.free.connection.ConnectionIO</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import doobie.syntax.string.toSqlInterpolator</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import doobie.util.fragment.Fragment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import fs2.Stream</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.DeleteBuilder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.SelectBuilder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.SelectBuilderSql</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.UpdateBuilder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">class EmailaddressRepoImpl extends EmailaddressRepo </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def delete(compositeId</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressId)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Boolean</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sql"""delete from person.emailaddress where "businessentityid" = $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">compositeId.businessentityid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> AND "emailaddressid" = $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">compositeId.emailaddressid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">""".update.run.map(_ </span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> 0)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def delete</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DeleteBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    DeleteBuilder("person.emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressFields)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def insert(unsaved</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRow)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sql"""insert into person.emailaddress("businessentityid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddressid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rowguid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> "modifieddate")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          values ($</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.businessentityid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">int4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.emailaddressid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">int4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.emailaddress</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.rowguid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">uuid</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.modifieddate</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">timestamp)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          returning "businessentityid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddressid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rowguid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> "modifieddate"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">text</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       """.query(EmailaddressRow.read).unique</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def insert(unsaved</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRowUnsaved)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    val fs = List(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      Some((Fragment.const0(s""""businessentityid"""")</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fr"$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.businessentityid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">int4"))</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      Some((Fragment.const0(s""""emailaddress"""")</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fr"$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.emailaddress</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">"))</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      unsaved.emailaddressid match </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        case Defaulted.UseDefault =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> None</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        case Defaulted.Provided(value) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> Some((Fragment.const0(s""""emailaddressid"""")</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fr"$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Int</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">int4"))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      unsaved.rowguid match </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        case Defaulted.UseDefault =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> None</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        case Defaulted.Provided(value) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> Some((Fragment.const0(s""""rowguid"""")</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fr"$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TypoUUID</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">uuid"))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      unsaved.modifieddate match </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        case Defaulted.UseDefault =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> None</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        case Defaulted.Provided(value) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> Some((Fragment.const0(s""""modifieddate"""")</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fr"$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TypoLocalDateTime</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">timestamp"))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ).flatten</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    val q = if (fs.isEmpty) </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      sql"""insert into person.emailaddress default values</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            returning "businessentityid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddressid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rowguid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> "modifieddate"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">text</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         """</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> else </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      val CommaSeparate = Fragment.FragmentMonoid.intercalate(fr"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      sql"""insert into person.emailaddress($</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">CommaSeparate.combineAllOption(fs.map </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> case (n</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> _) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> n </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">).get</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            values ($</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">CommaSeparate.combineAllOption(fs.map </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> case (_</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> f) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> f </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">).get</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            returning "businessentityid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddressid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rowguid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> "modifieddate"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">text</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         """</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    q.query(EmailaddressRow.read).unique</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def select</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> SelectBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    SelectBuilderSql("person.emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow.read)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def selectAll</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Stream</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ConnectionIO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sql"""select "businessentityid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddressid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rowguid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> "modifieddate"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">text from person.emailaddress""".query(EmailaddressRow.read).stream</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def selectById(compositeId</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressId)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Option</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sql"""select "businessentityid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddressid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rowguid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> "modifieddate"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">text from person.emailaddress where "businessentityid" = $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">compositeId.businessentityid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> AND "emailaddressid" = $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">compositeId.emailaddressid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">""".query(EmailaddressRow.read).option</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def update(row</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRow)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Boolean</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    val compositeId = row.compositeId</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sql"""update person.emailaddress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          set "emailaddress" = $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">row.emailaddress</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              "rowguid" = $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">row.rowguid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">uuid</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              "modifieddate" = $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">row.modifieddate</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">timestamp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          where "businessentityid" = $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">compositeId.businessentityid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> AND "emailaddressid" = $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">compositeId.emailaddressid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">"""</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      .update</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      .run</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      .map(_ </span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> 0)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def update</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> UpdateBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    UpdateBuilder("person.emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow.read)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def upsert(unsaved</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRow)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sql"""insert into person.emailaddress("businessentityid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddressid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rowguid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> "modifieddate")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          values (</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.businessentityid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">int4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.emailaddressid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">int4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.emailaddress</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.rowguid</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">uuid</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.modifieddate</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">timestamp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          )</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          on conflict ("businessentityid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> "emailaddressid")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          do update set</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            "emailaddress" = EXCLUDED."emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            "rowguid" = EXCLUDED."rowguid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            "modifieddate" = EXCLUDED."modifieddate"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          returning "businessentityid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddressid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"emailaddress"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rowguid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> "modifieddate"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">text</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       """.query(EmailaddressRow.read).unique</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>EmailaddressRepoMock.scala</summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/</span><span class="token important">**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * File has been automatically generated by `typo`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package adventureworks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package person</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package emailaddress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import doobie.free.connection.ConnectionIO</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import doobie.free.connection.delay</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import fs2.Stream</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import scala.annotation.nowarn</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.DeleteBuilder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.DeleteBuilder.DeleteBuilderMock</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.DeleteParams</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.SelectBuilder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.SelectBuilderMock</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.SelectParams</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.UpdateBuilder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.UpdateBuilder.UpdateBuilderMock</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import typr.dsl.UpdateParams</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">class EmailaddressRepoMock(toRow</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Function1</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRowUnsaved</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token key atrule" style="color:#00a4db">map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> scala.collection.mutable.Map</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = scala.collection.mutable.Map.empty) extends EmailaddressRepo </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def delete(compositeId</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressId)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Boolean</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    delay(map.remove(compositeId).isDefined)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def delete</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DeleteBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    DeleteBuilderMock(DeleteParams.empty</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> map)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def insert(unsaved</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRow)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    delay </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      val _ = if (map.contains(unsaved.compositeId))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        sys.error(s"id $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">unsaved.compositeId</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> already exists")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      else</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        map.put(unsaved.compositeId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> unsaved)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      unsaved</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def insert(unsaved</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRowUnsaved)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    insert(toRow(unsaved))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def select</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> SelectBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    SelectBuilderMock(EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> delay(map.values.toList)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> SelectParams.empty)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def selectAll</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Stream</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ConnectionIO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    Stream.emits(map.values.toList)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def selectById(compositeId</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressId)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Option</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    delay(map.get(compositeId))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def update(row</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRow)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Boolean</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    delay </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      map.get(row.compositeId) match </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        case Some(`row`) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> false</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        case Some(_) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          map.put(row.compositeId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">row)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> @nowarn</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        case None =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> false</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def update</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> UpdateBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    UpdateBuilderMock(UpdateParams.empty</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EmailaddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> map)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">override def upsert(unsaved</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">EmailaddressRow)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConnectionIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    delay </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      map.put(unsaved.compositeId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">unsaved)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> @nowarn</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      unsaved</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>EmailaddressRow.scala</summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/</span><span class="token important">**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * File has been automatically generated by `typo`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package adventureworks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package person</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package emailaddress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.customtypes.TypoLocalDateTime</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.customtypes.TypoUUID</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.person.businessentity.BusinessentityId</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import doobie.enumerated.Nullability</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import doobie.util.Get</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import doobie.util.Read</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import java.sql.ResultSet</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">case class EmailaddressRow(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  /</span><span class="token important">**</span><span class="token plain"> Primary key. Person associated with this email address.  Foreign key to Person.BusinessEntityID</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      Points to </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">person.PersonRow.businessentityid</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">businessentityid</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> BusinessentityId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  /</span><span class="token important">**</span><span class="token plain"> Primary key. ID of this email address. </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">emailaddressid</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Int</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  /</span><span class="token important">**</span><span class="token plain"> E</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">mail address for the person. </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">emailaddress</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Option</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">/* max 50 chars </span><span class="token important">*/</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">rowguid</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TypoUUID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">modifieddate</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TypoLocalDateTime</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token key atrule" style="color:#00a4db">val compositeId</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> EmailaddressId = EmailaddressId(businessentityid</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> emailaddressid)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">object EmailaddressRow </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">implicit lazy val read</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Read</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> =</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    new Read</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">EmailaddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      gets = List(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        (Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">BusinessentityId</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Nullability.NoNulls)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        (Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Int</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Nullability.NoNulls)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        (Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">/* max 50 chars </span><span class="token important">*/</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Nullability.Nullable)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        (Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">TypoUUID</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Nullability.NoNulls)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        (Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">TypoLocalDateTime</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Nullability.NoNulls)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      )</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">unsafeGet = (rs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ResultSet</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">i</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Int) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> EmailaddressRow(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        businessentityid = Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">BusinessentityId</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.unsafeGetNonNullable(rs</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i + 0)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        emailaddressid = Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Int</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.unsafeGetNonNullable(rs</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i + 1)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        emailaddress = Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">/* max 50 chars </span><span class="token important">*/</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.unsafeGetNullable(rs</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i + 2)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        rowguid = Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">TypoUUID</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.unsafeGetNonNullable(rs</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i + 3)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        modifieddate = Get</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">TypoLocalDateTime</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.unsafeGetNonNullable(rs</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i + 4)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      )</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    )</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>EmailaddressRowUnsaved.scala</summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/</span><span class="token important">**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * File has been automatically generated by `typo`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package adventureworks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package person</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">package emailaddress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.customtypes.Defaulted</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.customtypes.TypoLocalDateTime</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.customtypes.TypoUUID</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import adventureworks.person.businessentity.BusinessentityId</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">/</span><span class="token important">**</span><span class="token plain"> This class corresponds to a row in table `person.emailaddress` which has not been persisted yet </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">case class EmailaddressRowUnsaved(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  /</span><span class="token important">**</span><span class="token plain"> Primary key. Person associated with this email address.  Foreign key to Person.BusinessEntityID</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    * Points to </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">person.PersonRow.businessentityid</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">businessentityid</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> BusinessentityId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  /</span><span class="token important">**</span><span class="token plain"> E</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">mail address for the person. </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">emailaddress</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Option</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">/* max 50 chars </span><span class="token important">*/</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">/** Default</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> nextval('person.emailaddress_emailaddressid_seq'</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">regclass)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    * Primary key. ID of this email address.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">emailaddressid</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Defaulted</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Int</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = Defaulted.UseDefault</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">/** Default</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> uuid_generate_v1() </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">rowguid</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Defaulted</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">TypoUUID</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = Defaulted.UseDefault</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">/** Default</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> now() </span><span class="token important">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">modifieddate</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Defaulted</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">TypoLocalDateTime</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> = Defaulted.UseDefault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">) </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">def toRow(emailaddressidDefault</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> Int</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">rowguidDefault</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> TypoUUID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">modifieddateDefault</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">=&gt; TypoLocalDateTime)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> EmailaddressRow =</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    EmailaddressRow(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      businessentityid = businessentityid</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      emailaddress = emailaddress</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      emailaddressid = emailaddressid match </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                         case Defaulted.UseDefault =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> emailaddressidDefault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                         case Defaulted.Provided(value) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                       </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      rowguid = rowguid match </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  case Defaulted.UseDefault =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> rowguidDefault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  case Defaulted.Provided(value) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      modifieddate = modifieddate match </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                       case Defaulted.UseDefault =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> modifieddateDefault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                       case Defaulted.Provided(value) =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                     </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    )</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details>
<p>In total it's about this much:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">--------------------------------------------------------------------------------</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Language             Files        Lines        Blank      Comment         Code</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--------------------------------------------------------------------------------</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Scala                 1052        47011         3215         7436        36360</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--------------------------------------------------------------------------------</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="initial-comparison-of-compile-times">Initial comparison of compile times<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#initial-comparison-of-compile-times" class="hash-link" aria-label="Direct link to Initial comparison of compile times" title="Direct link to Initial comparison of compile times">​</a></h2>
<p>Each benchmark is run three times, and in the graphs you can choose to see minimum or average compile times.</p>
<div style="width:80%;margin:auto"><select id="toggleView"><option value="min" selected="">Minimum Compile Time</option><option value="avg">Average Compile Time</option></select><div class="chart-container"><canvas id="groupedBarChart1" width="800" height="400"></canvas></div></div>
<p>"baseline" is generating just case classes, no type class instances or repositories.</p>
<p>We can make some observations right away:</p>
<ul>
<li>Scala 3 is ~always faster than Scala 2.12 and 2.13, only beaten by Scala 2.12 for baseline/just case classes</li>
<li>doobie takes more than double the time to compile compared to anorm and zio-jdbc for Scala 2.x.</li>
<li>zio-jdbc and anorm have similar compile times across scala versions.</li>
<li>It's interesting to see the "cost" of adding type class instances and repositories</li>
</ul>
<br>
<div style="background-color:#f0f0f0;color:#000;padding:20px;border-radius:8px;display:flex;align-items:center;justify-content:center"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:10px"><path d="M7 20v1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1"></path><path d="M9 20h6"></path><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 16h-2v-2h2v2zm0-4h-2V8h2v6z"></path></svg><span>Key takeaway: <p>Scala 3 is consistently fast! Great job Scala team!</p></span></div>
<br>
<p>The meat of this blog post will be to <b>investigate why the code for doobie takes so long for scala 2.x</b>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="so-whats-up-with-doobie-with-scala-2x">So what's up with doobie with Scala 2.x?<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#so-whats-up-with-doobie-with-scala-2x" class="hash-link" aria-label="Direct link to So what's up with doobie with Scala 2.x?" title="Direct link to So what's up with doobie with Scala 2.x?">​</a></h2>
<p>The issue is composite. Let's take the biggest issue first - Automatic derivation of type class instances!</p>
<p>Let's take something rather innocent:</p>
<div class="language-scala codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-scala codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> A</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v1</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v2</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v3</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v4</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v5</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v6</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v7</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token string-interpolation id function" style="color:#d73a49">sql</span><span class="token string-interpolation string" style="color:#e3116c">"select 1,2,3,4,5,6,7"</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">query</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">to</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">List</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token string-interpolation id function" style="color:#d73a49">sql</span><span class="token string-interpolation string" style="color:#e3116c">"select 1,2,3,4,5,6,7"</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">query</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">to</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">List</span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will compile and work, but an instance of <code>Read[A]</code> will be derived for each of the two queries.</p>
<p>No problem, we're taught that we can cache the <code>Read[A]</code> instance in the companion object.</p>
<div class="language-scala codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-scala codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">object</span><span class="token plain"> A </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">implicit</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> read</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Read</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> Read</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">derived</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The surprise is that (as far as I understand) this does not actually work in this case.
Since the automatic derivation is put in implicit scope in the companion object of the type class, it will be found before our cached instance.
We actually need to specify the instance explicitly:</p>
<div class="language-scala codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-scala codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token string-interpolation id function" style="color:#d73a49">sql</span><span class="token string-interpolation string" style="color:#e3116c">"select 1,2,3,4,5,6,7"</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">query</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">read</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">to</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">List</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token string-interpolation id function" style="color:#d73a49">sql</span><span class="token string-interpolation string" style="color:#e3116c">"select 1,2,3,4,5,6,7"</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">query</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">read</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">to</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">List</span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And boom! We've solved the problem. I implemented this in Typo, and will refer to this as doobie with and without fix in subsequent tables.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="results-without-accidental-automatic-type-class-derivation-for-doobie">Results without accidental automatic type class derivation for doobie<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#results-without-accidental-automatic-type-class-derivation-for-doobie" class="hash-link" aria-label="Direct link to Results without accidental automatic type class derivation for doobie" title="Direct link to Results without accidental automatic type class derivation for doobie">​</a></h2>
<div style="width:80%;margin:auto"><select id="toggleView"><option value="min" selected="">Minimum Compile Time</option><option value="avg">Average Compile Time</option></select><div class="chart-container"><canvas id="groupedBarChart2" width="800" height="400"></canvas></div></div>
<p>Fantastic! We've cut the compile times almost in half for doobie for Scala 2.x - ten seconds is a lot of time if you suffer them often.</p>
<br>
<div style="background-color:#f0f0f0;color:#000;padding:20px;border-radius:8px;display:flex;align-items:center;justify-content:center"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:10px"><path d="M7 20v1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1"></path><path d="M9 20h6"></path><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 16h-2v-2h2v2zm0-4h-2V8h2v6z"></path></svg><span>Key takeaway: <p>Automatic typeclass derivation is a bad idea, but only for Scala 2.x!</p></span></div>
<br>
<p>But doobie is still a lot slower, so let's dig a bit further!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="query-interpolation-woes">Query interpolation woes.<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#query-interpolation-woes" class="hash-link" aria-label="Direct link to Query interpolation woes." title="Direct link to Query interpolation woes.">​</a></h2>
<p>So all of this extra time is spent in typer/resolving implicits. I wanted to see what could be done about it, and what causes it.</p>
<p>That's why I implemented an "inline implicits" mode for typo. I'll show a diff of what it does here, hopefully it'll be clear that it hardcodes some implicit resolution:</p>
<div class="language-diff codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-diff codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+import doobie.syntax.SqlInterpolator.SingleFragment.fromWrite</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+import doobie.util.Write</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+import doobie.util.meta.Meta</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">class EmailaddressRepoImpl extends EmailaddressRepo {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   override def update(row: EmailaddressRow): ConnectionIO[Boolean] = {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     val compositeId = row.compositeId</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     sql"""update person.emailaddress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-          set "emailaddress" = ${row.emailaddress},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-              "rowguid" = ${row.rowguid}::uuid,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-              "modifieddate" = ${row.modifieddate}::timestamp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-          where "businessentityid" = ${compositeId.businessentityid} AND "emailaddressid" = ${compositeId.emailaddressid}"""</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+          set "emailaddress" = ${fromWrite(row.emailaddress)(Write.fromPutOption(Meta.StringMeta.put))},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+              "rowguid" = ${fromWrite(row.rowguid)(Write.fromPut(TypoUUID.put))}::uuid,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+              "modifieddate" = ${fromWrite(row.modifieddate)(Write.fromPut(TypoLocalDateTime.put))}::timestamp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+          where "businessentityid" = ${fromWrite(compositeId.businessentityid)(Write.fromPut(BusinessentityId.put))} AND "emailaddressid" = ${fromWrite(compositeId.emailaddressid)(Write.fromPut(Meta.IntMeta.put))}"""</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       .update</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       .run</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       .map(_ &gt; 0)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here are the results with and without inlined implicits:</p>
<div style="width:80%;margin:auto"><select id="toggleView"><option value="min" selected="">Minimum Compile Time</option><option value="avg">Average Compile Time</option></select><div class="chart-container"><canvas id="groupedBarChart3" width="800" height="400"></canvas></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="observations">Observations<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#observations" class="hash-link" aria-label="Direct link to Observations" title="Direct link to Observations">​</a></h3>
<ul>
<li>This brings the compile time for doobie down to about the same as for anorm and zio-jdbc!</li>
<li>We lose a handsome amount of compile time for zio-jdbc and anorm. But it's less clear that it's enough to be worth inlining manually.
It's a great conclusion actually, resolving implicits is fast as long as it's a straightforward process.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="great-so-what-is-going-on-with-doobie-then">Great! So what is going on with doobie then?<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#great-so-what-is-going-on-with-doobie-then" class="hash-link" aria-label="Direct link to Great! So what is going on with doobie then?" title="Direct link to Great! So what is going on with doobie then?">​</a></h3>
<p>I honestly haven't dug into all the details, but I have a guess which looks obvious.
In order to interpolate values into an SQL query, doobie needs to resolve a chain of implicits instead of just one.</p>
<p>In order to interpolate in the <code>emailaddress</code> field which has type <code>Option[String]</code>, this thing needs to be resolved:</p>
<div class="language-scala codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-scala codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">doobie</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">syntax</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">SqlInterpolator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">SingleFragment</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fromWrite</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">unsaved</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">emailaddress</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  doobie</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">util</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Write</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fromPutOption</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    doobie</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">util</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Put</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">metaProjectionWrite</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        doobie</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">util</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">meta</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Meta</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">StringMeta</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>I'm sure this can cause the compiler to spend a lot of time looking around the companion objects of
<code>SingleFragment</code>, <code>Write</code>, <code>Put</code>, and <code>Meta</code>.</p>
<br>
<div style="background-color:#f0f0f0;color:#000;padding:20px;border-radius:8px;display:flex;align-items:center;justify-content:center"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:10px"><path d="M7 20v1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1"></path><path d="M9 20h6"></path><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 16h-2v-2h2v2zm0-4h-2V8h2v6z"></path></svg><span>Key takeaway: <p>Make the compiler's job easy! It probably shouldn't need to go through so many layers at all.</p></span></div>
<br>
<div style="background-color:#f0f0f0;color:#000;padding:20px;border-radius:8px;display:flex;align-items:center;justify-content:center"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:10px"><path d="M7 20v1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1"></path><path d="M9 20h6"></path><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 16h-2v-2h2v2zm0-4h-2V8h2v6z"></path></svg><span>Key takeaway: <p>Scala 3 must have some caching of resolved implicits that Scala 2.x doesn't have.</p></span></div>
<br>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="future-work-on-benchmark">Future work on benchmark<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#future-work-on-benchmark" class="hash-link" aria-label="Direct link to Future work on benchmark" title="Direct link to Future work on benchmark">​</a></h2>
<p>Here are other things things I've done to speed up compilation of generated code, based on observations as I was developing.
A future version of the benchmark could measure the effect of these changes as well. Reach out if you're interesting in contributing towards this.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="avoiding-anonymous-classes">Avoiding anonymous classes<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#avoiding-anonymous-classes" class="hash-link" aria-label="Direct link to Avoiding anonymous classes" title="Direct link to Avoiding anonymous classes">​</a></h3>
<p>Let's have a look at the code for <code>doobie.postgres.Text[A]</code>, it's basically this:</p>
<div class="language-scala codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-scala codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">trait</span><span class="token plain"> Text</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> outer </span><span class="token keyword" style="color:#00009f">=&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> unsafeEncode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> A</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sb</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> StringBuilder</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">Unit</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">object</span><span class="token plain"> Text </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> instance</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">f</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> StringBuilder</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">=&gt;</span><span class="token plain"> </span><span class="token builtin">Unit</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Text</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> Text</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> unsafeEncode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> A</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sb</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> StringBuilder</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sb</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Using <code>Text.instance</code> instead of <code>new Text[A]</code> saves some compilation time because it generates less bytecode.</p>
<p>If you're a library author you should consider adding such a constructor method.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="avoiding-automatic-derivation-of-product-type-class-instances">Avoiding automatic derivation of product type class instances<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#avoiding-automatic-derivation-of-product-type-class-instances" class="hash-link" aria-label="Direct link to Avoiding automatic derivation of product type class instances" title="Direct link to Avoiding automatic derivation of product type class instances">​</a></h3>
<p>Typo reimplements the derivation of type class instances for product types, so the benchmark cannot measure the cost of this so far.
If you expand <code>EmailaddressRow.scala</code> above, you'll see that <code>Read[EmailaddressRow]</code> is always implemented as <code>new Read(...)</code>.</p>
<p>It would be very interesting to measure the cost of deriving this automatically as well, we just need to patch <code>Typo</code> to use <code>Read.derived</code> instead of <code>new Read(...)</code>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="avoiding-type-aliases">Avoiding type aliases<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#avoiding-type-aliases" class="hash-link" aria-label="Direct link to Avoiding type aliases" title="Direct link to Avoiding type aliases">​</a></h3>
<p>Doobie uses a pattern where <code>doobie.util.Read</code> is exposed as <code>doobie.Read</code> through a baroque mechanism:</p>
<div class="language-scala codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-scala codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">package</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">object</span><span class="token plain"> doobie</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> Aliases</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">trait</span><span class="token plain"> Aliases </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> Types </span><span class="token keyword" style="color:#00009f">with</span><span class="token plain"> Modules</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">trait</span><span class="token plain"> Types </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** @group Type Aliases - Core */</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> Read</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> doobie</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">util</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Read</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">A</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Typo always generates the fully qualified name <code>doobie.util.Read</code>.
It would be interesting to measure if there is a cost associated with this as well.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="final-results-and-limitations">Final results and limitations<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#final-results-and-limitations" class="hash-link" aria-label="Direct link to Final results and limitations" title="Direct link to Final results and limitations">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="json-libraries">JSON libraries<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#json-libraries" class="hash-link" aria-label="Direct link to JSON libraries" title="Direct link to JSON libraries">​</a></h3>
<p>This last graph includes compilation time for three JSON libraries as well, basically just generating type class instances for them.
I excluded them for the text above since there was nothing interesting to say about the results.
You can see how "inline implicits" mode also speeds up compilation of these JSON codecs.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="benchmark-limitations">Benchmark limitations<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#benchmark-limitations" class="hash-link" aria-label="Direct link to Benchmark limitations" title="Direct link to Benchmark limitations">​</a></h3>
<p>I think part of this improvement from "inlined implicits" is due to the fact that the compiler is a bit warmer since it will just have finished compiling without inlined implicits.</p>
<p>Note specifically that we get faster compiles for "baseline" with "inlined implicits" mode, although the generated code is the same.</p>
<p>I didn't bother improving the benchmark more, because the interesting things mentioned above was very visible and consistent already.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="final-graph">Final graph<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#final-graph" class="hash-link" aria-label="Direct link to Final graph" title="Direct link to Final graph">​</a></h3>
<div style="width:80%;margin:auto"><select id="toggleView"><option value="min" selected="">Minimum Compile Time</option><option value="avg">Average Compile Time</option></select><div class="chart-container"><canvas id="groupedBarChart4" width="800" height="400"></canvas></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="reproducing-the-results">Reproducing the results<a href="https://typo.oyvindberg.dev/blog/the-cost-of-implicits/#reproducing-the-results" class="hash-link" aria-label="Direct link to Reproducing the results" title="Direct link to Reproducing the results">​</a></h2>
<p>You can clone the <a href="https://github.com/oyvindberg/typr" target="_blank" rel="noopener noreferrer">repo</a> and run <code>bleep compile-benchmarks</code> to reproduce the results.
The benchmark code can be found in <a href="https://github.com/oyvindberg/typr/blob/main/typr-scripts/src/scala/scripts/CompileBenchmark.scala" target="_blank" rel="noopener noreferrer">CompileBenchmark.scala</a></p>]]></content:encoded>
            <category>typo</category>
            <category>scala</category>
            <category>doobie</category>
            <category>anorm</category>
            <category>zio-jdbc</category>
            <category>implicits</category>
            <category>compile-times</category>
        </item>
        <item>
            <title><![CDATA[Hello, ZIO]]></title>
            <link>https://typo.oyvindberg.dev/blog/hello-zio/</link>
            <guid>https://typo.oyvindberg.dev/blog/hello-zio/</guid>
            <pubDate>Fri, 24 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Typo ported to ZIO]]></description>
            <content:encoded><![CDATA[<p>Thanks to the efforts of Jules Ivanic in <a href="https://github.com/oyvindberg/typr/pull/57" target="_blank" rel="noopener noreferrer">PR #57</a>,
Typo now supports using <code>zio-jdbc</code> as a database library.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="never-heard-of-typo">Never heard of Typo?<a href="https://typo.oyvindberg.dev/blog/hello-zio/#never-heard-of-typo" class="hash-link" aria-label="Direct link to Never heard of Typo?" title="Direct link to Never heard of Typo?">​</a></h3>
<p>You can check out the <a href="https://oyvindberg.github.io/typo/db/" target="_blank" rel="noopener noreferrer">introduction</a>.
Essentially it's a code generator for database access code, which makes PostgreSQL integration type-safe and wonderful to use.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="maturity">Maturity<a href="https://typo.oyvindberg.dev/blog/hello-zio/#maturity" class="hash-link" aria-label="Direct link to Maturity" title="Direct link to Maturity">​</a></h3>
<p>Note that <code>zio-jdbc</code> is a bit less mature than <code>doobie</code> and <code>anorm</code>, so it's a bit more likely to be some rough edges.
In particular, it handles nullable values <a href="https://github.com/zio/zio-jdbc/issues/188" target="_blank" rel="noopener noreferrer">imperfectly</a>.
We fixed a bunch of issues while working on this PR, so it should be pretty close.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="implemented-missing-features-in-zio-jdbc">Implemented missing features in <code>zio-jdbc</code><a href="https://typo.oyvindberg.dev/blog/hello-zio/#implemented-missing-features-in-zio-jdbc" class="hash-link" aria-label="Direct link to implemented-missing-features-in-zio-jdbc" title="Direct link to implemented-missing-features-in-zio-jdbc">​</a></h3>
<p><code>zio-jdbc</code> does not support postgres arrays, and it does not support
the <a href="https://typo.oyvindberg.dev/db/other-features/streaming-inserts/">COPY API for streaming inserts</a>.</p>
<p>Typo outputs code which implements both of these features.</p>
<p>This can likely be upstreamed as a postgres integration module in <code>zio-jdbc</code> at some point.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="repository-signatures">Repository signatures<a href="https://typo.oyvindberg.dev/blog/hello-zio/#repository-signatures" class="hash-link" aria-label="Direct link to Repository signatures" title="Direct link to Repository signatures">​</a></h3>
<p>To give a taste of the code you'll get, consider this repository definition:</p>
<div class="language-scala codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-scala codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">trait</span><span class="token plain"> AddressRepo </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> delete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">addressid</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> AddressId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">Boolean</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> delete</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DeleteBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">AddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> insert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">unsaved</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> insertStreaming</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">unsaved</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZStream</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> batchSize</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">Int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">Long</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> insert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">unsaved</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> AddressRowUnsaved</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/* NOTE: this functionality requires PostgreSQL 16 or later! */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> insertUnsavedStreaming</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">unsaved</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZStream</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AddressRowUnsaved</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> batchSize</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">Int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">Long</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> select</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> SelectBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">AddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> selectAll</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZStream</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> selectById</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">addressid</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> AddressId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Option</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> selectByIds</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">addressids</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Array</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">AddressId</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZStream</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> update</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">row</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">Boolean</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> update</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UpdateBuilder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">AddressFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> upsert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">unsaved</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> AddressRow</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ZIO</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ZConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Throwable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> UpdateResult</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Notice how the signatures use <code>ZIO</code>, <code>ZStream</code>, <code>ZConnection</code>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="zio-schema-is-not-used"><code>zio-schema</code> is not used<a href="https://typo.oyvindberg.dev/blog/hello-zio/#zio-schema-is-not-used" class="hash-link" aria-label="Direct link to zio-schema-is-not-used" title="Direct link to zio-schema-is-not-used">​</a></h3>
<p>We opted to <em>not</em> go through zio-schema for the generated code. It was not clear that it was possible to implement all
PostgreSQL features through <code>zio-schema</code>, and we wanted to generate code which is as <a href="https://typo.oyvindberg.dev/db/other-features/faster-compilation/">fast to compile</a> as possible.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="also-support-for-zio-json">Also support for <code>zio-json</code><a href="https://typo.oyvindberg.dev/blog/hello-zio/#also-support-for-zio-json" class="hash-link" aria-label="Direct link to also-support-for-zio-json" title="Direct link to also-support-for-zio-json">​</a></h3>
<p>Typo supports generating <a href="https://typo.oyvindberg.dev/db/other-features/json/">JSON codecs</a> for all the row types.
The PR also adds support for <code>zio-json</code>, so you can get codecs like this:</p>
<div class="language-scala codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-scala codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">object</span><span class="token plain"> AddressRow </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">implicit</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">lazy</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> jsonDecoder</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> JsonDecoder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">implicit</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">lazy</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> jsonEncoder</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> JsonEncoder</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">AddressRow</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content:encoded>
            <category>typo</category>
            <category>zio</category>
        </item>
    </channel>
</rss>