<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Christoph Hermann</title>
    <description>The latest articles on Forem by Christoph Hermann (@stoeffel).</description>
    <link>https://forem.com/stoeffel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F9862%2F1217681.jpeg</url>
      <title>Forem: Christoph Hermann</title>
      <link>https://forem.com/stoeffel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/stoeffel"/>
    <language>en</language>
    <item>
      <title>DRY Vim</title>
      <dc:creator>Christoph Hermann</dc:creator>
      <pubDate>Wed, 06 Nov 2019 20:43:58 +0000</pubDate>
      <link>https://forem.com/stoeffel/dry-vim-2b0</link>
      <guid>https://forem.com/stoeffel/dry-vim-2b0</guid>
      <description>&lt;p&gt;I believe Vim's biggest strength is that it removes a lot of repetition in my workflow. This post is a short (probably incomplete) list of commands that allow you to repeat an action without having to repeat the whole sequence of keystrokes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editing
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Repeats the last change you've made.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Repeat last macro.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Repeat last command.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Searching
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Repeat last &lt;code&gt;f&lt;/code&gt;, &lt;code&gt;F&lt;/code&gt;, &lt;code&gt;t&lt;/code&gt;, or &lt;code&gt;T&lt;/code&gt; motion.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;,&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Same as &lt;code&gt;;&lt;/code&gt; but in the opposite direction.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cgn&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Apply last change to next search result.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Macros
&lt;/h2&gt;

&lt;p&gt;Macros are a handy tool in your toolbox to avoid repetition.&lt;br&gt;
It's crucial to practice, though, and memorize some patterns that make creating macros simpler and reusable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start at the beginning
&lt;/h3&gt;

&lt;p&gt;To create reusable macros you need to make the changes as generic as possible. This means that you need to avoid starting the recording at a specific point in the code snippet. It's best to first move to the start of the line &lt;code&gt;0&lt;/code&gt; or the start of the first word in the line &lt;code&gt;^&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigate to generic places
&lt;/h3&gt;

&lt;p&gt;If you need to navigate in your macro it's best to avoid navigating using &lt;code&gt;hjkl&lt;/code&gt;. Navigate to special characters that are common on the lines you'd like to change or navigate to the start or end of a line.&lt;/p&gt;

&lt;p&gt;I wrote about macros a long time ago if you'd like to learn more techniques. &lt;a href="https://medium.com/@schtoeffel/you-don-t-need-more-than-one-cursor-in-vim-2c44117d51db"&gt;https://medium.com/@schtoeffel/you-don-t-need-more-than-one-cursor-in-vim-2c44117d51db&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Plugins
&lt;/h2&gt;

&lt;p&gt;Plugins can mess up repeating changes with &lt;code&gt;.&lt;/code&gt;. For example, changing the surrounding quotes with double quotes using &lt;a href="https://github.com/tpope/vim-surround"&gt;vim-surround&lt;/a&gt; (&lt;code&gt;cs'"&lt;/code&gt;) isn't repeatable. There is a plugin though that fixes this for (at least) some plugins &lt;a href="https://github.com/tpope/vim-repeat"&gt;vim-repeat&lt;/a&gt;. You don't need to configure anything, just install it using your plugin manager of choice and you're good to go.&lt;/p&gt;

&lt;p&gt;I hope you were able to learn a trick or two from this post to level-up your vim skills 🙂.&lt;/p&gt;

&lt;p&gt;If you're curious to check out how my vim config looks like then head over to &lt;a href="https://github.com/whimsical-vim/whimsical-vim"&gt;https://github.com/whimsical-vim/whimsical-vim&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>editing</category>
      <category>programming</category>
    </item>
    <item>
      <title>Type-Safe MySQL Queries via Postgres </title>
      <dc:creator>Christoph Hermann</dc:creator>
      <pubDate>Tue, 05 Nov 2019 08:19:05 +0000</pubDate>
      <link>https://forem.com/noredink/type-safe-mysql-queries-via-postgres-5cnk</link>
      <guid>https://forem.com/noredink/type-safe-mysql-queries-via-postgres-5cnk</guid>
      <description>&lt;h1&gt;
  
  
  Type-Safe MySQL Queries via Postgres
&lt;/h1&gt;

&lt;p&gt;My team and I are working on NoRedInk's transition from Ruby on Rails and MySQL to Haskell and Postgres. A major benefit of our new stack (Postgres/Haskell/Elm) is type-safety between the boundaries (db to backend, backend to frontend). To ensure our code is type-safe between Haskell and &lt;a href="(https://elm-lang.org/)"&gt;Elm&lt;/a&gt; we use &lt;a href="https://www.servant.dev/"&gt;servant&lt;/a&gt;. Servant allows us to generate types and functions for Elm based on our APIs. To ensure type-safety between Postgres and Haskell we use &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt;. This means that when we change our database schema, our Haskell code won't compile if there is a mismatch, similarly to how our Elm code won't compile if there is a mismatch with our backend endpoints.  We're going to focus on type-safety between our databases and Haskell in this post and on how we introduced MySQL into this.  But first, let's briefly look at how we can check out Postgres queries at compile-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Postgres-Typed
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;PGConnection&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Todo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="n"&gt;postgresConn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class="n"&gt;pgQuery&lt;/span&gt;
      &lt;span class="n"&gt;postgresConn&lt;/span&gt;
      &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pgSQL&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;!
        SELECT id, description, completed
        FROM todos
        WHERE user_id = ${userId}
        ORDER BY id ASC
      &lt;span class="o"&gt;|]&lt;/span&gt;
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="n"&gt;todoFromRow&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We use &lt;a href="https://wiki.haskell.org/Template_Haskell"&gt;Template Haskell&lt;/a&gt; to write SQL queries instead of a DSL, allowing our engineers to use their existing knowledge of SQL instead of having to learn some library. &lt;code&gt;pgSQL&lt;/code&gt; is a &lt;a href="https://wiki.haskell.org/Quasiquotation"&gt;&lt;code&gt;QuasiQuoter&lt;/code&gt;&lt;/a&gt; it creates a value of type &lt;code&gt;PGQuery&lt;/code&gt; which gets executed by &lt;code&gt;pgQuery&lt;/code&gt;. The quasi quoted query gets verified against the database schema and executed (ignoring results and without arguments) at compile-time. This is all we need to know from &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt; for this post, but I recommend checking out the &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;docs&lt;/a&gt; and looking at their &lt;a href="https://github.com/dylex/postgresql-typed/blob/master/test/Main.hs"&gt;example&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving to Haskell and Postgres
&lt;/h2&gt;

&lt;p&gt;Our Rails application uses a MySQL database. Gradually moving functionality/new features to Haskell often means that we need access to data that isn't yet moved.  We solved this initially by creating an endpoints on our Rails application and requested the data via http. This proved to be toilsome and complicated development and deploys, and therefore made it harder for teams to commit to building things in Haskell. In order to remove this hurdle, we started to think about reading data directly from our MySQL database. We really liked &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt;, because it gave us the ability to write actual SQL queries and type-safety between the database and Haskell. Unfortunatlly, there isn’t a mysql-typed, but we found an interesting solution provided by Postgres itself; foreign-data-wrappers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Foreign Data Wrappers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://wiki.postgresql.org/wiki/Foreign_data_wrappers"&gt;Foreign Data Wrappers&lt;/a&gt; (short fdw) offer a way to manage remote data directly within your Postgres database. This allows us to use &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt; to access the MySQL data via Postgres.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;SERVER&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;schema&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;DATA&lt;/span&gt; &lt;span class="n"&gt;WRAPPER&lt;/span&gt; &lt;span class="n"&gt;mysql_fdw&lt;/span&gt;
  &lt;span class="k"&gt;OPTIONS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;host&lt;/span&gt; &lt;span class="s1"&gt;'${host}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="s1"&gt;'${port}'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Mapping for the application user, so it can perform queries.&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="n"&gt;MAPPING&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="err"&gt;${&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;SERVER&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;schema&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;OPTIONS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="s1"&gt;'${username}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="s1"&gt;'${passphrase}'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;schema&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;AUTHORIZATION&lt;/span&gt; &lt;span class="err"&gt;${&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;IMPORT&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="err"&gt;${&lt;/span&gt;&lt;span class="n"&gt;dbname&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;SERVER&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;schema&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;schema&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Unfortunately, we quickly ran into problems when converting http requests to the Rails application with queries directly to MySQL. Fdw has some limitations that were blockers for use. The schema imported as a fdw is imported without any constraints other than &lt;code&gt;NOT NULL&lt;/code&gt;. An even bigger problem was that some SQL constructs weren’t pushed down to MySQL. As an example the fdw wouldn’t forward &lt;code&gt;LIMIT&lt;/code&gt; clauses and therefore grab all rows of a table, send them over the wire, and then apply the &lt;code&gt;LIMIT&lt;/code&gt; in Postgres. This obviously has huge performance implications and meant that we needed to find a different solution without suffering type-safety.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type-Safe MySQL Queries
&lt;/h2&gt;

&lt;p&gt;We had three options; either find a library that would give us the guarantees we were used to from &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt; for MySQL, building our own library or somehow abusing &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt;.  Building our own library wasn't an option because that would have exceeded the scope of this project, and we couldn't find a library that met our requirements.  Fortunately, &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt; allows us to access &lt;code&gt;getQueryString&lt;/code&gt; to get the raw query string from the quasi-quoted query. This we can then execute with &lt;a href="http://hackage.haskell.org/package/mysql-simple-0.4.5"&gt;mysql-simple&lt;/a&gt; instead of &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt;. This allows us to check MySQL and Postgres queries at compile time using a fdw, but connecting directly to Postgres and MySQL at runtime.  Finally we can write queries to our MySQL database using the same API as for Postgres and having full type-safety between the database and Haskell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;cats&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;MySQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Simple&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Connection&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;cats&lt;/span&gt; &lt;span class="n"&gt;mySQLConnection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class="kt"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;MySQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Simple&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_&lt;/span&gt;
      &lt;span class="n"&gt;mySQLConnection&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="c1"&gt;-- direct connection to MySQL&lt;/span&gt;
      &lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="s"&gt;"mysql-schema-name."&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;
      &lt;span class="c1"&gt;-- ^ The schemaname (fdw) only exists during compile time.&lt;/span&gt;
      &lt;span class="n"&gt;getQueryString&lt;/span&gt; &lt;span class="n"&gt;unknownPGTypeEnv&lt;/span&gt;
      &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pgSql&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;!
        SELECT id, description, color
        FROM mysql-schema-name.cats
        ORDER BY id ASC
      &lt;span class="o"&gt;|]&lt;/span&gt;
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="n"&gt;catFromRow&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I’ve inlined the functions from &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt; and mysql-simple to keep the code examples simple. We actually have two modules &lt;code&gt;MySQL&lt;/code&gt; and &lt;code&gt;Postgres&lt;/code&gt; that abstract the database specific functions away allowing us to use the exact same API for both databases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;We need to prefix tables with the schema name that we used to import the fdw (see &lt;code&gt;mysql-schema-name.cats&lt;/code&gt; in the example above). Without the prefix the compilation won't succeed. The problem is that we don't have a schema with this name at runtime. We can simply work around this by running &lt;code&gt;Text.replace "mysql-schema-name." "" sqlString&lt;/code&gt; before executing the query.  Queries need to use standard SQL features and shouldn't rely on MySQL specific features. This is actually kind of a feature, because it forces us to write queries in a way that simplifies converting them to Postgres later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While this is a nice solution for us, I don't really recommend you to use MySQL in this way. This solution allows us to simplify the transition between Rails/MySQL and Haskell/Postgres. I would love for library like &lt;a href="https://hackage.haskell.org/package/postgresql-typed-0.6.1.0"&gt;postgresql-typed&lt;/a&gt; to exist for MySQL, but it wasn't feasable to build such a thing. Honestly, I don't even know if it would be possible. I hope this post showed you how to create a nice experience for transitioning to a different technology.&lt;br&gt;
Thanks for reading ❤️&lt;/p&gt;




&lt;p&gt;Special thanks to everyone involved in building this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/asterite"&gt;Ary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/allenap"&gt;Gavin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/jwoudenberg"&gt;Jasper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.mavnn.co.uk/"&gt;Michael&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>haskell</category>
      <category>postgres</category>
      <category>mysql</category>
      <category>noredink</category>
    </item>
  </channel>
</rss>
