<?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>DEV Community: Eliya Cohen</title>
    <description>The latest articles on DEV Community by Eliya Cohen (@newbie012).</description>
    <link>https://dev.to/newbie012</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%2F415845%2F6f5a2eb5-76fe-4b50-9d82-c50e12917e37.jpeg</url>
      <title>DEV Community: Eliya Cohen</title>
      <link>https://dev.to/newbie012</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/newbie012"/>
    <language>en</language>
    <item>
      <title>You may not need an SQL query builder or ORM</title>
      <dc:creator>Eliya Cohen</dc:creator>
      <pubDate>Thu, 06 Oct 2022 19:12:58 +0000</pubDate>
      <link>https://dev.to/newbie012/you-may-not-need-an-sql-query-builder-or-orm-5e2d</link>
      <guid>https://dev.to/newbie012/you-may-not-need-an-sql-query-builder-or-orm-5e2d</guid>
      <description>&lt;p&gt;The are three levels of forms to interact with our database:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Raw SQL (also known as native SQL)&lt;/li&gt;
&lt;li&gt;Query Builder&lt;/li&gt;
&lt;li&gt;ORM&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Raw SQL
&lt;/h2&gt;

&lt;p&gt;With great power comes great responsibility. Raw SQL gives us the most low-level form of interaction with our database. This may lead to lots of issues. Namely SQL injections, typos, low-editor support, and typescript types support (we don't want to manually maintain the types).&lt;/p&gt;

&lt;h2&gt;
  
  
  Query Builder
&lt;/h2&gt;

&lt;p&gt;A query builder can solve most of the Raw SQL approach. It does so by supplying wrapper functions rather than actually writing raw queries. It may look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;person&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pet.owner_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;person.id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;first_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pet.name as pet_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;person.id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;executeTakeFirst&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Taken from &lt;a href="https://github.com/koskimas/kysely#minimal-example"&gt;Kysely&lt;/a&gt; Minimal example.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While it does solve most of the issues of writing raw SQL, it has its own cons as well (This is not specific to Kysely):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don't get complete control over how you run your queries.&lt;/li&gt;
&lt;li&gt;You don't know what SQL query is actually being run.&lt;/li&gt;
&lt;li&gt;You can't simply copy-paste the query into your PgAdmin/DataGrip to debug your query.&lt;/li&gt;
&lt;li&gt;Language-specific syntax is limited (such as coalesce, functions, etc.).&lt;/li&gt;
&lt;li&gt;You're bound to the technology you're using. It can be cumbersome if you switch to a new library after a while.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ORMs
&lt;/h2&gt;

&lt;p&gt;ORMs are usually the most high-level interaction form with your database. It gives you a more declarative approach to interacting with your database. Given the example I shown above, Let's compare it with Prisma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findFirst&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While it's more rows than we've written before, you don't need to define how &lt;code&gt;pet&lt;/code&gt; is related to &lt;code&gt;person&lt;/code&gt; since the ORM handles it for you. While it's more simplified compared to query builder (which can be controversial), it has its own cons as well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's more limited than a query builder (note that I couldn't add a column alias (&lt;code&gt;pet.name as pet_name&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;All of what I mentioned with query builder cons.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  There's no silver bullet. Or is it?
&lt;/h2&gt;

&lt;p&gt;Going back to raw SQL - What if you had a tool that allowed us to keep writing SQL while taking care of the abovementioned issues?&lt;/p&gt;

&lt;p&gt;Today, there are popular SQL libraries help you write safe queries from SQL injections (such as Prisma and Postgres.js) using a tagged template syntax. &lt;a href="https://dev.to/newbie012/please-dont-manually-parameterize-your-sql-queries-3m7k"&gt;I wrote a more in-depth post about it here&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`SELECT name FROM person WHERE id = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="c1"&gt;// Will be evaluated to&lt;/span&gt;
&lt;span class="c1"&gt;// { query: "SELECT name FROM person WHERE id = $1, values: [id] }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But still, we're left with these issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The query is open to typos.&lt;/li&gt;
&lt;li&gt;Missing typescript support.&lt;/li&gt;
&lt;li&gt;Open to runtime errors (such as ambiguous column names).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there was a tool that plugs into your linter (ESLint) and helps you find and fix these issues, would you use it? Luckily, I just wrote one - &lt;a href="https://github.com/ts-safeql/safeql"&gt;SafeQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Demo:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/757656695" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Using this plugin will ensure the following:&lt;/p&gt;

&lt;p&gt;Your query has neither language typos nor table/column typos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`SELECT idd FROM comments`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="o"&gt;~~~&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;column&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;idd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;does&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;exist&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your query has the correct type annotation. If a query doesn't have a type or has an invalid type, SafeQL will auto-fix it for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`SELECT id FROM comments`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;~~~~~~~~~~~~&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;missing&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;annotation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your query won't have invalid where clauses (e.g., comparing an integer column to a boolean value).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM comments WHERE body = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                                                       &lt;span class="o"&gt;~&lt;/span&gt;
                        &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;operator&lt;/span&gt; &lt;span class="nx"&gt;does&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;exist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;integer&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since SafeQL is a plugin and not an SQL library, it gives you the following benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you want to drop the plugin, you can simply remove it from ESLint, and everything should still be ok.&lt;/li&gt;
&lt;li&gt;You can use whatever SQL library you want (Although libraries that don't come with a built-in sql tagged literal will have to install a third-party package, such as &lt;a href="https://safeql.dev/libraries/sql-tag/introduction.html"&gt;@ts-safeql/sql-tag&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;If you care about bundle size, then you might be happy to know that SafeQL adds zero kilobytes to your bundle size since it's not a runtime code (just like any other ESLint plugin/rule).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While it does solve many issues, it's not perfect.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlike ORMs and Query Builders, SafeQL doesn't have an auto-complete syntax.&lt;/li&gt;
&lt;li&gt;SafeQL is still actively developed. Although it hasn't reached a stable release yet, it has proven itself in a large codebase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you feel adventurous and want to try out SafeQL, be sure to check out the &lt;a href="https://safeql.dev/guide/getting-started.html"&gt;Getting Started&lt;/a&gt; page in the documentation 🙂&lt;/p&gt;

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

&lt;p&gt;Query Builders and ORMs are solutions to problems. SafeQL is another solution. Each one has its downsides. In one project, we may prefer one solution over the other. In a different project, we may prefer mixing two solutions. It's really up to you.&lt;/p&gt;




&lt;p&gt;Disclaimer: I'm not against using SQL query builders. While the solution I wrote solves most of what the query builder solves, each solution has its pros and cons.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>postgres</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Please Don't (Manually) Parameterize Your SQL Queries</title>
      <dc:creator>Eliya Cohen</dc:creator>
      <pubDate>Fri, 16 Sep 2022 14:36:01 +0000</pubDate>
      <link>https://dev.to/newbie012/please-dont-manually-parameterize-your-sql-queries-3m7k</link>
      <guid>https://dev.to/newbie012/please-dont-manually-parameterize-your-sql-queries-3m7k</guid>
      <description>&lt;p&gt;Last week, I wrote a &lt;a href="https://dev.to/newbie012/write-sql-queries-with-confidence-typescript-postgres-5b61"&gt;post&lt;/a&gt; about a plugin (that lints your SQL queries) called &lt;a href="https://safeql.dev"&gt;SafeQL&lt;/a&gt;. While doing so, I wrote this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM comments WHERE id = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Immediately, I got responses from a few places that I should &lt;a href="https://www.reddit.com/r/javascript/comments/xbb4ge/comment/inz5tbn"&gt;parameterize&lt;/a&gt; &lt;a href="https://www.reddit.com/r/javascript/comments/xbb4ge/comment/inyqdw3"&gt;my&lt;/a&gt; &lt;a href="https://dev.to/raibtoffoletto/comment/21hip"&gt;queries&lt;/a&gt; since it's open for SQL injections.&lt;/p&gt;

&lt;p&gt;While they are not entirely wrong, they are not correct.&lt;/p&gt;

&lt;p&gt;I'll explain; writing variables inside a query string is indeed a call for SQL injection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ⚠️ Open to SQL injection&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM comments WHERE id = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// id = "0 OR (other statement)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While that is true, it is not what is happening in the code below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM comments WHERE id = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="c1"&gt;// ^^^ tagged templated literal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What is this syntax?
&lt;/h2&gt;

&lt;p&gt;It is called &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates"&gt;Tagged templates&lt;/a&gt;, and I am quoting MDN:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tags allow you to parse template literals with a function. The first argument of a tag function contains an array of string values. The remaining arguments are related to the expressions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Explain to me like I am 5
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// this line&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM comments WHERE id = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// turns into this:&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM comments WHERE id = $1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sql&lt;/code&gt; (which is a tagged template literal) is a function that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TemplateStringsArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Typescript built-in type&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TemplateStringsArray&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Given the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM comments WHERE id = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="c1"&gt;// template === ["SELECT * FROM comments WHERE id = "]&lt;/span&gt;
&lt;span class="c1"&gt;// values === [id]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;template&lt;/code&gt; would be equal to &lt;code&gt;["SELECT * FROM comments WHERE id = "]&lt;/code&gt; and values to &lt;code&gt;[id]&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  But how node-postgres or Sequelize handle it?
&lt;/h2&gt;

&lt;p&gt;After we demystified the term tagged template literal, how can we use it to our favor?&lt;/p&gt;

&lt;p&gt;node-postgres allows writing SQL queries by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// string only approach&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;select name FROM table_name WHERE id = $1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// object approach&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;select name FROM table_name WHERE id = $1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sequelize allows us to write in an object approach as well (among others), but with &lt;code&gt;query&lt;/code&gt; rather than a &lt;code&gt;text&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;select name FROM table_name WHERE id = $1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we might have noticed, the object structure is similar to the same structure that the &lt;code&gt;sql&lt;/code&gt; tag has returned. In other words, when using &lt;code&gt;sql&lt;/code&gt; tag, it returns an object that resembles a parameterized query.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;sql&lt;/code&gt; implementation in a nutshell
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TemplateStringsArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`$&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// we pass both `query` and `text` so it would be compatible with both&lt;/span&gt;
  &lt;span class="c1"&gt;// node-postgres and Sequelize:&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why should I use it over manually parameterized queries?
&lt;/h2&gt;

&lt;p&gt;It is easier, safer, less error-prone, and more straightforward. Large queries can go up to dozens of parameters. It is just a matter of time before they will be misplaced. In addition, reading the query while trying to figure out what is &lt;code&gt;$5&lt;/code&gt; or &lt;code&gt;$14&lt;/code&gt; can be challenging.&lt;/p&gt;

&lt;h2&gt;
  
  
  npm install
&lt;/h2&gt;

&lt;p&gt;Instead of maintaining an sql implementation, there are a few packages that have already done it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/@ts-safeql/sql-tag"&gt;@ts-safeql/sql-tag&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/sql-template-strings"&gt;sql-template-strings&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/sql-template-tag"&gt;sql-template-tag&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;If you are using TypeScript and care about type safety, check out &lt;a href="https://safeql.dev"&gt;SafeQL&lt;/a&gt;. It is a free and open-source ESLint plugin that ensures you never misspell a table, column, or any invalid syntax. As a plus, it automatically generates TypeScript types for each query you write.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>sql</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Write SQL Queries With Confidence (TypeScript + Postgres)</title>
      <dc:creator>Eliya Cohen</dc:creator>
      <pubDate>Sat, 10 Sep 2022 22:34:37 +0000</pubDate>
      <link>https://dev.to/newbie012/write-sql-queries-with-confidence-typescript-postgres-5b61</link>
      <guid>https://dev.to/newbie012/write-sql-queries-with-confidence-typescript-postgres-5b61</guid>
      <description>&lt;p&gt;TL;DR- Check out &lt;a href="https://safeql.dev" rel="noopener noreferrer"&gt;https://safeql.dev&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Problem
&lt;/h2&gt;

&lt;p&gt;Usually, we tend to operate against our database using ORMs such as Prisma, Sequelize, TypeORM, etc.&lt;/p&gt;

&lt;p&gt;Most of the time, these libraries deliver a great DX, but in some cases, they can be limited. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The library doesn't support a feature that you need.&lt;/li&gt;
&lt;li&gt;The actual query that the library is generating is not optimal.&lt;/li&gt;
&lt;li&gt;You have a complex query that writing it using the library is either impossible or hard to maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In all of these cases, we find ourselves writing raw queries. At first, we might even write some tests around it to make sure&lt;br&gt;
we won't mess it up in the future. Then, we might even manually write our types for each query.&lt;/p&gt;

&lt;p&gt;Times go by, and you find yourself with a bunch of raw queries, and each time you write another one, you lose confidence. Then, your colleagues write more migrations, which becomes quite hard to follow.&lt;/p&gt;

&lt;p&gt;That's where &lt;a href="https://safeql.dev" rel="noopener noreferrer"&gt;SafeQL&lt;/a&gt; comes into play.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is SafeQL?
&lt;/h2&gt;

&lt;p&gt;SafeQL is a plugin for ESLint that helps you write safe raw queries.&lt;/p&gt;

&lt;p&gt;It does so by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checking your raw queries for syntax errors (e.g., trying to select a column that doesn't exist).&lt;/li&gt;
&lt;li&gt;Warn you about type errors (e.g., trying to compare a string to an integer)&lt;/li&gt;
&lt;li&gt;Warn you about missing/incorrect query TS types (and suggest fixes).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What does it look like?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

client.query(sql`SELECT idd FROM comments`);
                        ~~~ // Error: column "idd" does not exist


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

function getById(id: number) {
    client.query(sql`SELECT * FROM comments WHERE body = ${id}`);
                                                       ~
                     // Error: operator does not exist: text = integer
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

client.query(sql`SELECT id FROM comments`);
~~~~~~~~~~~~ // Error: Query is missing type annotation


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Here's a tweet that demonstrates it on live&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1564036318229073921-996" src="https://platform.twitter.com/embed/Tweet.html?id=1564036318229073921"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1564036318229073921-996');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1564036318229073921&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Ok, how do I use it?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.safeql.dev/guide/getting-started.html" rel="noopener noreferrer"&gt;See documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, you need to install the plugin:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @ts-safeql/eslint-plugin libpg-query


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, you need to add the plugin to your ESLint config:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@ts-safeql/eslint-plugin"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Finally, it depends on whether you want to get your type validation from a migrations folder or a database URL.&lt;br&gt;
For simplicity's sake, we'll be using &lt;a href="https://www.prisma.io/" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt; as our ORM and validate against a database URL:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@ts-safeql/check-sql"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"connections"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"databaseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgres://postgres:postgres@localhost:5432/my_database"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prisma"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"operators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"$queryRaw"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  What's going on here?
&lt;/h3&gt;

&lt;p&gt;As you might've seen, &lt;code&gt;connections&lt;/code&gt; is an array rather than a single object. That's because you can have multiple connections.&lt;br&gt;
For example, you might have a &lt;code&gt;mainClient&lt;/code&gt; for your main database and a &lt;code&gt;subClient&lt;/code&gt; for your sub-database.&lt;br&gt;
In most cases, you would only have one connection.&lt;/p&gt;

&lt;p&gt;Each connection has the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;databaseUrl&lt;/code&gt;: The database URL to connect to.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: The variable name that holds the connection (for example, &lt;code&gt;prisma&lt;/code&gt; for &lt;code&gt;prisma.$queryRaw(...)&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;operators&lt;/code&gt;: An array of operators you use to execute queries (for example, &lt;code&gt;prisma&lt;/code&gt; for &lt;code&gt;prisma.$queryRaw(...)&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Take it for a spin
&lt;/h3&gt;

&lt;p&gt;Now you have everything set up!&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Prisma&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$queryRaw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                       &lt;span class="o"&gt;~~~~~~~~~~~~~~~~&lt;/span&gt; &lt;span class="c1"&gt;// Error: Query is missing type annotation&lt;/span&gt;
    &lt;span class="nx"&gt;Prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM users  WHERE id = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;SafeQL is currently in its very early stages, but we can make it better with the community's help! If you have any ideas/improvements/bugs to share, be sure to &lt;a href="https://github.com/ts-safeql/safeql/issues/new/choose" rel="noopener noreferrer"&gt;file an issue&lt;/a&gt; in our GitHub repository.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>postgres</category>
      <category>javascript</category>
      <category>sql</category>
    </item>
  </channel>
</rss>
