<?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: Matthieu Blandineau</title>
    <description>The latest articles on DEV Community by Matthieu Blandineau (@mblandineau).</description>
    <link>https://dev.to/mblandineau</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%2F817620%2Ffcde308b-6d6f-4f9b-b556-ab46c34ffde9.jpeg</url>
      <title>DEV Community: Matthieu Blandineau</title>
      <link>https://dev.to/mblandineau</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mblandineau"/>
    <language>en</language>
    <item>
      <title>MongoDB Cheat Sheet</title>
      <dc:creator>Matthieu Blandineau</dc:creator>
      <pubDate>Mon, 23 May 2022 11:35:05 +0000</pubDate>
      <link>https://dev.to/forestadmin/mongodb-cheat-sheet-2bf1</link>
      <guid>https://dev.to/forestadmin/mongodb-cheat-sheet-2bf1</guid>
      <description>&lt;p&gt;We gathered a list of handy MongoDB and mongosh commands and queries when working with MongoDB databases. Please ping us &lt;a href="https://twitter.com/ForestAdmin"&gt;@ForestAdmin&lt;/a&gt; if you’d like to add something to the cheat sheet!&lt;/p&gt;

&lt;p&gt;This is the second post from our Cheat Sheets series following the &lt;a href="https://blog.forestadmin.com/postgresql-cheat-sheet/"&gt;PostgreSQL&lt;/a&gt; one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with MongoDB
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/mongodb-shell/install/#std-label-mdb-shell-install"&gt;Install MongoDB Shell mongosh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Login and enter MongoDB Shell mongosh&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mongosh
//OR
$ mongosh "mongodb://localhost:27017"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;List MongoDB databases&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;Connect to MongoDB database&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;Exit MongoDB Shell mongosh&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Managing MongoDB
&lt;/h2&gt;

&lt;p&gt;Check MongoDB version&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.version()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Check if MongoDB is running&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pgrep -fa -- -D | grep mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Restart MongoDB on Linux&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.shutdownServer()
$ sudo systemctl start mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Restart MongoDB on Mac OSX&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ brew services stop mongodb-community@yourMongodbVersionNumber
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Restart MongoDB on Windows&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Winkey + R
Type "services.msc"
Search "MondoDb"
Click "restart"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Change MongoDB user password&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.changeUserPassword(username, NewPassword)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Exit from mongosh&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Interacting with MongoDB databases
&lt;/h2&gt;

&lt;p&gt;List MongoDB databases&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;show dbs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Connect or switch to MongoDB database&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;Create new MongoDB database&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;Show name of the current database&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.getName()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Delete MongoDB database&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.dropDatabase()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Rename MongoDB database&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mongodump -d oldDatabaseName path
$ mongorestore -d newDatabaseName path/oldDatabaseName.bson
$ mongosh
use oldDatabaseName
db.dropDatabase()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Interacting with MongoDB collections
&lt;/h2&gt;

&lt;p&gt;List MongoDB collections&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;show collections
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Describe MongoDB collection&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.getCollectionInfos( { name: "collectionName" } )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Describe all collections in MongoDB database&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.getCollectionInfos()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create MongoDB collection&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.createCollection("collectionName", options)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Delete MongoDB collection&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.drop()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Rename MongoDB collection&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.oldCollectionName.renameCollection("newCollectionName")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Interacting with MongoDB indexes
&lt;/h2&gt;

&lt;p&gt;List MongoDB indexes in a collection&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.getIndexes()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create a MongoDB index in a collection&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.createIndex(keys, options, commitQuorum)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create multiple MongoDB indexes in a collection&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.createIndexes( [ keyPatterns ], options, commitQuorum )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Delete MongoDB index&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.dropIndex("indexName")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Delete all indexes in MongoDB collection&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collection.dropIndexes()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Rebuild MongoDB indexes&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collection.reIndex()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Interacting with MongoDB documents
&lt;/h2&gt;

&lt;p&gt;Count documents in a MongoDB collection&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.countDocuments()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;List all documents in a MongoDB collection&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.find().toArray()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create document in MongoDB&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.insertOne(
   &amp;lt;document&amp;gt;
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Display a document in MongoDB&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.find({ "_id": documentID })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Update a document in MongoDB&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.updateOne(
    { "_id": documentID },
    &amp;lt;update&amp;gt;
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Delete a document in MongoDB&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.deleteOne({ "_id": documentID })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace a document in MongoDB&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.collectionName.replaceOne(
    { "_id": documentID },
    &amp;lt;replacement&amp;gt;
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Backup and restore MongoDB database
&lt;/h2&gt;

&lt;p&gt;Backup MongoDB database&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mongodump -d oldDatabaseName path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Restore MongoDB database&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mongorestore -d newDatabaseName path/oldDatabaseName.bson
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Managing roles, users and permissions in MongoDB
&lt;/h2&gt;

&lt;p&gt;List MongoDB roles&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.getRoles(
    {
      rolesInfo: 1
    }
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create MongoDB user&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.createUser(
    {
        user: "userName",

        pwd: "userPassword",

        roles:[{role: "roleName" , db:"databaseName"}]
    }
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Delete MongoDB user&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.dropUser(userName)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Change MongoDB user password&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.changeUserPassword(userName, newPassword)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;em&gt;Need to build admin panels or a GUI tool for MongoDB?&lt;/em&gt; &lt;a href="https://www.forestadmin.com/integrations/mongodb"&gt;&lt;em&gt;Check out Forest Admin for MongoDB&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>database</category>
      <category>mongodb</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Most popular PostgreSQL GUIs in 2022: the (almost) scientific list</title>
      <dc:creator>Matthieu Blandineau</dc:creator>
      <pubDate>Tue, 17 May 2022 12:12:03 +0000</pubDate>
      <link>https://dev.to/forestadmin/most-popular-postgresql-guis-in-2022-the-almost-scientific-list-3e22</link>
      <guid>https://dev.to/forestadmin/most-popular-postgresql-guis-in-2022-the-almost-scientific-list-3e22</guid>
      <description>&lt;p&gt;Wjether you're starting with PostgreSQL (in which case you might fancy a &lt;a href="https://blog.forestadmin.com/postgresql-cheat-sheet/"&gt;cheat sheet&lt;/a&gt;) and looking for the best postgres GUI or postgres client to get started, or you're a veteran (in which case ... you might also fancy a &lt;a href="https://blog.forestadmin.com/postgresql-cheat-sheet/"&gt;cheat sheet&lt;/a&gt;!) and you've hit the limit of your current tool — or you just can't stand it anymore, this list is for you. We've compiled the most popular postgreSQL GUIs and clients &lt;strong&gt;among your postgres developers peers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before we jump in, a few words about the methodology: we started from the list of PostgreSQL clients referenced on the &lt;a href="https://wiki.postgresql.org/wiki/PostgreSQL_Clients"&gt;PostgreSQL official wiki&lt;/a&gt;. For each client, we looked at the number of occurrences of their name in &lt;a href="https://www.reddit.com/r/PostgreSQL/"&gt;r/PostgreSQL&lt;/a&gt; discussions and comments. Of course, this methodology has some limitations, including: r/PostgreSQL developers are not &lt;em&gt;all&lt;/em&gt; the PostgreSQL developers in the world and we only count the postgres clients mentions, not whether a mention is positive or negative. So it's not a list of "best postgres GUIs". But what's a &lt;em&gt;best&lt;/em&gt; postgres GUI anyway, as its value will most likely depend on your needs? Let's start&lt;/p&gt;

&lt;h2&gt;
  
  
  1. pgAdmin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---sjcjphF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---sjcjphF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-3.png" alt="pgAdmin postgres client" width="880" height="692"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.pgadmin.org/"&gt;pgAdmin&lt;/a&gt; is the most popular PostgreSQL GUI. It is purpose built for Postgres and supports all its features and operations. pgAdmin is open source and also supports Postgres derivative databases such as &lt;a href="https://www.enterprisedb.com/product-compatibility"&gt;EDB Postgres Advanced Server&lt;/a&gt;. You can test it live &lt;a href="https://www.katacoda.com/enterprisedb/scenarios/pgadmin-sandbox"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pgAdmin supported platforms&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can install pgAdmin on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Linux&lt;/li&gt;
&lt;li&gt;  macOS&lt;/li&gt;
&lt;li&gt;  Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then access it locally or over internet via your navigator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You can run pgAdmin as a web application, on your computer or on any server, meaning you can use pgAdmin to access and manage distributed Postgres databases, from anywhere.&lt;/li&gt;
&lt;li&gt;  pgAdmin allows you to create, read and edit all PostgreSQL objects&lt;/li&gt;
&lt;li&gt;  You can easily rearrange its UI&lt;/li&gt;
&lt;li&gt;  pgAdmin offers advanced server monitoring capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  pgAdmin isn't as straight forward to install on your desktop as other postgres clients&lt;/li&gt;
&lt;li&gt;  pgAdmin is more suited for administrating your PostgreSQL than developing on it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;pgAdmin pricing:&lt;/strong&gt; pgAdmin is free and open source&lt;/p&gt;

&lt;h2&gt;
  
  
  2. DBeaver
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--biTN05u---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--biTN05u---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-4.png" alt="DBeaver postgres client" width="880" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dbeaver.io/"&gt;DBeaver&lt;/a&gt; is a widely used multi database GUI tool, particularly popular among postgreSQL developers. Just like pgAdmin, it's open source. In addition to postgreSQL, it supports MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Apache Hive, Phoenix, Presto, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DBeaver supported platforms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Linux&lt;/li&gt;
&lt;li&gt;  macOS&lt;/li&gt;
&lt;li&gt;  Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  DBeaver is super easy to install as a desktop application, and to connect to your PostgreSQL database&lt;/li&gt;
&lt;li&gt;  DBeaver offers a visual query builder to create advanced SQL queries without advanced (or any) knowledge of SQL&lt;/li&gt;
&lt;li&gt;  It comes with strong data access, search, visualization and edition capabilities&lt;/li&gt;
&lt;li&gt;  DBeaver also offers a fake data generator to populate your database and test it and the applications built on it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  DBeaver runs locally and is sometimes resource intensive, which can lead to performance issues&lt;/li&gt;
&lt;li&gt;  And that's pretty much it! Other than that, PostgreSQL DBeaver users haven't expressed strong concerns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DBeaver pricing:&lt;/strong&gt; DBeaver is free and open source&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Postico
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S8Z2set8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S8Z2set8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-5.png" alt="Postico PostgreSQL client" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eggerapps.at/postico/"&gt;Postico&lt;/a&gt; is macOS PostgreSQL client for reading data, doing basic manual data entry and editing your database structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Postico supported platforms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  macOS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Postico is extremely straight forward to execute basic tasks over your PostgreSQL database&lt;/li&gt;
&lt;li&gt;  Postico easy to install and to securely connect to your Postgres database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Postico's strenghts are also its weaknesses: it doesn't offer advanced administration, monitoring or querying capabilities&lt;/li&gt;
&lt;li&gt;  Postico is only available on macOS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Postico pricing:&lt;/strong&gt; $39.99 for 1 user, $319.99 for 10 users, free trial with feature limitations but no time limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. DataGrip
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Aros8LSa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jetbrains.com/datagrip/img/screenshots/query-console.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Aros8LSa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jetbrains.com/datagrip/img/screenshots/query-console.png" alt="DataGrip PostgreSQL client" width="880" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.jetbrains.com/datagrip/"&gt;DataGrip&lt;/a&gt; is a multi database IDE to install locally, that can act as your Postgres GUI and much more. It is developed by JetBrains who are known for their numerous dev tools. On top of Postgres, it supports MySQL, Oracle Database, Redshift, MariaDB, Cassandra, &lt;a href="https://blog.forestadmin.com/mongodb-cheat-sheet/"&gt;MongoDB&lt;/a&gt; and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DataGrip supported platforms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Linux&lt;/li&gt;
&lt;li&gt;  macOS&lt;/li&gt;
&lt;li&gt;  Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Powerful data viewer and editor&lt;/li&gt;
&lt;li&gt;  Great and customisable UI&lt;/li&gt;
&lt;li&gt;  A lot of powerful features to develop on your PostgreSQL database, such as context and schema based code completion, and real-time bug detection in your code (and fix suggestions!).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  DataGrip can be resource intensive&lt;/li&gt;
&lt;li&gt;  Because it's much more than a Postgres client, DataGrip can be a bit overwhelming for beginners&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DataGrip pricing:&lt;/strong&gt; $89 per year for individual users, $199 per user per year for organisations, with commitment and product packs options.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Navicat
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YRQiL7Kz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.navicat.com/images/product_screenshot/02.Product_01_Premium_Windows_01_Mainscreen_FR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YRQiL7Kz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.navicat.com/images/product_screenshot/02.Product_01_Premium_Windows_01_Mainscreen_FR.png" alt="Navicat PostgreSQL GUI" width="880" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.navicat.com/en/products/navicat-for-postgresql"&gt;Navicat&lt;/a&gt; is a GUI focused on database development. As it is multi database, on top of acting as your PostgreSQL GUI, it can connect MySQL, MariaDB, MongoDB, SQL Server, Oracle, PostgreSQL, and SQLite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Navicat supported platforms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Linux&lt;/li&gt;
&lt;li&gt;  macOS&lt;/li&gt;
&lt;li&gt;  iOS&lt;/li&gt;
&lt;li&gt;  Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Easy and powerful SQL development tools, such as a visual SQL builder, code completion and customisable Code Snippets.&lt;/li&gt;
&lt;li&gt;  Good database structure visualisation and edition capabilities.&lt;/li&gt;
&lt;li&gt;  Collaboration feature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Limited PostgreSQL database administration capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Navicat pricing:&lt;/strong&gt; $349.99 per year for non commercial usage, $699.99 per year for commercial usage, with different commitment options&lt;/p&gt;

&lt;h2&gt;
  
  
  6. TablePlus
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lk5exCm2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lk5exCm2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-7.png" alt="TablePlus Postgres GUI" width="880" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tableplus.com/"&gt;TablePlus&lt;/a&gt; is a database management GUI supporting various databases including MySQL, Redshift, Redis, MongoDB and of course PostgreSQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TablePlus supported platforms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Linux&lt;/li&gt;
&lt;li&gt;  macOS&lt;/li&gt;
&lt;li&gt;  iOS&lt;/li&gt;
&lt;li&gt;  iPadOS&lt;/li&gt;
&lt;li&gt;  Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Clean and intuitive data browsing, querying and editing UI&lt;/li&gt;
&lt;li&gt;  Various and easy to use security features&lt;/li&gt;
&lt;li&gt;  Good query editor including autocomplete, highlight syntax, query reformatter and history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  TablePlus doesn't go deep in any specific area (for instance PostgreSQL development or monitoring). But is it really a con?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TablePlus pricing:&lt;/strong&gt; from $49 to $99&lt;/p&gt;

&lt;h2&gt;
  
  
  7. OmniDB
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EyQW-M2---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/OmniDB/doc/master/img/omnidb_3/dashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EyQW-M2---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/OmniDB/doc/master/img/omnidb_3/dashboard.png" alt="OmniDB PostgreSQL GUI" width="880" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omnidb.readthedocs.io/en/latest/en/01_introduction.html"&gt;OmniDB&lt;/a&gt; is a browser-based app to access and manage various databases such as Oracle and MySQL. And of course, it can act as your PostgreSQL client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OmniDB supported platforms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Linux&lt;/li&gt;
&lt;li&gt;  macOS&lt;/li&gt;
&lt;li&gt;  Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  OmniDB supports plugins, so developers can add functionalities to their PostgreSQL GUI&lt;/li&gt;
&lt;li&gt;  It can be accessed by multiple users from several computers, making it a good option to collaborate on your PostgreSQL databases&lt;/li&gt;
&lt;li&gt;  OmniDB offers intuitive data editing features such as ability to copy and paste blocks&lt;/li&gt;
&lt;li&gt;  Good SQL editing with a customisable SQL editor featuring syntax highlight and code completion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://omnidb.readthedocs.io/en/latest/index.html"&gt;Light documentation&lt;/a&gt; especially on the usage of the tool&lt;/li&gt;
&lt;li&gt;  OmniDB is more complex than a Postico or TablePlus but less advanced than a DataGrip or Navicat. It's a good free option but maybe less complete than DBeaver, which has a &lt;a href="https://github.com/dbeaver/dbeaver/wiki"&gt;better documentation&lt;/a&gt; and a seemingly larger community.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;OmniDB pricing:&lt;/strong&gt; free and open source&lt;/p&gt;

&lt;h2&gt;
  
  
  8. SQuirreL SQL
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V2P9k_3s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V2P9k_3s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-8.png" alt="SquirreL Postgres GUI" width="880" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://squirrel-sql.sourceforge.io/"&gt;SquirreL SQL&lt;/a&gt; is a Java tool to view the structure of databases, browse their data, issue SQL commands and more. It supports many databases including SQL Server, MySQL, Oracle Database and of course PostgreSQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Squirrel SQL Supported platforms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Linux&lt;/li&gt;
&lt;li&gt;  Mac OS&lt;/li&gt;
&lt;li&gt;  Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  SquirreL SQL supports Java plugins to extend its capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Configuration is hard for first time users&lt;/li&gt;
&lt;li&gt;  The interface isn't the most intuitive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;SquirreL SQL pricing:&lt;/strong&gt; free and open source&lt;/p&gt;

&lt;h2&gt;
  
  
  9. HeidiSQL
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0U5N71NE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.heidisql.com/images/screenshots/database.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0U5N71NE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.heidisql.com/images/screenshots/database.png" alt="HeidiSQL Postgres GUI" title="Details about tables and views. Switchable column headers. Used to rename, delete, empty and modify tables." width="880" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.heidisql.com/"&gt;HeidiSQL&lt;/a&gt; is a client supporting various databases including MariaDB, MySQL and PostgreSQL. It's been built with the goal of being easy to learn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HeidiSQL supported platforms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  HeidiSQL is particularly good at managing several databases/servers simultaneously. Not only it can connect to multiple servers, but allows direct exports from one server or database to another and search across all the connected databases from the same server.&lt;/li&gt;
&lt;li&gt;  HeidiSQL is easy to install as a Windows app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Limited to Windows&lt;/li&gt;
&lt;li&gt;  Users have reported that the tool can be quite buggy&lt;/li&gt;
&lt;li&gt;  HeidiSQL doesn't provide advanced code debugging features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;HeidiSQL pricing:&lt;/strong&gt; free and open source&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Shameless plug: Forest Admin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/9d153914272d07052d905ce6e3445bbcc2916b64e2e7efa21b0f0e382a50b8ba/68747470733a2f2f666f726573742d6173736574732e73332e616d617a6f6e6177732e636f6d2f4769746875622b524541444d452b6173736574732f637275642e6a706567" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/9d153914272d07052d905ce6e3445bbcc2916b64e2e7efa21b0f0e382a50b8ba/68747470733a2f2f666f726573742d6173736574732e73332e616d617a6f6e6177732e636f6d2f4769746875622b524541444d452b6173736574732f637275642e6a706567" alt="Forest Admin PostgreSQL GUI" width="2880" height="1800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Forest Admin is an admin panel builder that can easily act as your Postgres GUI. It's packaged as a web application, with backend component to install on your servers. Upon installation, Forest Admin introspects your database and automatically creates a GUI including &lt;a href="https://blog.forestadmin.com/build-a-crud-app-for-your-database/"&gt;CRUD&lt;/a&gt; operations and tables visualisation, as well as functionalities like search, filters, pagination, exports and more. You can then customise it, add your custom actions or data visualisations.&lt;/p&gt;

&lt;p&gt;Forest Admin is focused on easing the visualisation and manipulation of your PostgreSQL database data, even by non technical users, from anywhere with an internet connection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forest Admin pricing:&lt;/strong&gt; free for 1 user, then $24 to $48 per user per month, commitment options.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Need to build admin panels or a GUI tool for PostgreSQL?&lt;/em&gt; &lt;em&gt;&lt;a href="https://www.forestadmin.com/integrations/postgresql?utm_source=blog&amp;amp;utm_medium=blog-organic&amp;amp;utm_campaign=blog-organic&amp;amp;utm_content=blog-postgres-gui"&gt;Check out Forest Admin for PostgreSQL&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>postgres</category>
      <category>database</category>
      <category>tooling</category>
    </item>
    <item>
      <title>What is a CRUD app and how to build one?</title>
      <dc:creator>Matthieu Blandineau</dc:creator>
      <pubDate>Thu, 12 May 2022 12:11:04 +0000</pubDate>
      <link>https://dev.to/forestadmin/what-is-a-crud-app-and-how-to-build-one-2016</link>
      <guid>https://dev.to/forestadmin/what-is-a-crud-app-and-how-to-build-one-2016</guid>
      <description>&lt;p&gt;Virtually any application involves users – or other applications it connects with – interacting with data stored in a database. Those interactions can be summarised in four operations: create, read (or view), update and delete. Those are the CRUD operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  CRUD operations explained
&lt;/h2&gt;

&lt;p&gt;More concretely, what are CRUD operations? Let’s use our &lt;a href="https://community.forestadmin.com/"&gt;community forum&lt;/a&gt; as an example.&lt;/p&gt;

&lt;h3&gt;
  
  
  CRUD operations descriptions and examples
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CREATE&lt;/strong&gt; – Being a forum, it needs to let our users create new topics. When a user opens the topic creation form, fills it and clicks on the "Create topic" button, it will trigger the forum's CREATE function that will create a new "Topic" record with the "title", "content", "tags", etc values in the forum's database&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GV4f9Ipy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.10.41.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GV4f9Ipy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.10.41.png" alt="CRUD CREATE" width="880" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;READ&lt;/strong&gt; – Once the post is created, anyone will be able to read it when browsing on the forum and clicking on it, or directly accessing its URL. Doing so will call the forum's READ function, that will retrieve the topic including its attributes (title, content, tags, etc) from the database. The READ function doesn't modify any information from this topic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Kf9RY8-j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.13.42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Kf9RY8-j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.13.42.png" alt="CRUD READ" width="880" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; – After a user has created a topic, our forum allows them to edit it. Useful if they made a mistake or forgot something. To do so, users can simply click the edit button and modify the values of the different attributes. After they click "Save Edit", the forum's UPDATE function will be called, and change those values accordingly in the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7RQaJ1LW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.12.30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7RQaJ1LW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.12.30.png" alt="CRUD UPDATE" width="880" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KRubYN4C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.13.05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KRubYN4C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.13.05.png" alt="CRUD UPDATE form" width="880" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DELETE&lt;/strong&gt; – If for any reason, the user wants to delete their topic, they can click the "delete topic" button,. The forum's DELETE function will be called, and will delete the topic record and its attributes from the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rBZpIJE8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.15.14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rBZpIJE8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/Screenshot-2022-05-03-at-16.15.14.png" alt="CRUD DELETE" width="880" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a simple explanation of CRUD operations on a single type of records. Even basic applications will involve CRUD operations on various types of records, with different users being authorised to perform different operations on different types of records. In our forums examples, a user can CREATE a topic, UPDATE their account, READ comments in a topic, and DELETE a bookmark, while admins can UPDATE users rights or CREATE new forum sections.&lt;/p&gt;

&lt;h3&gt;
  
  
  CRUD operations, REST and SQL
&lt;/h3&gt;

&lt;p&gt;Now we know what are CRUD operations at a high level. We saw that essentially, CRUD operations are triggered by users' (or automated) actions, and alter or read the database. Usually, in web applications, those CRUD operations will be triggered by users' actions generating calls to a REST API, and will alter or read the database via SQL queries.&lt;/p&gt;

&lt;p&gt;The table below describes how CRUD operations map to HTTP methods from REST APIs called to trigger the operations, and to SQL queries performed to alter or read the database:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RFXRTSm---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k91paf0q4nl6w72pe44u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RFXRTSm---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k91paf0q4nl6w72pe44u.png" alt="CRUD Table" width="880" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a CRUD app?
&lt;/h2&gt;

&lt;p&gt;A you might have noticed, even for the most basic use case, those CRUD operations aren't enough to achieve any meaningful results by themselves, they interact with other elements. All together, those elements make a CRUD app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Front-end
&lt;/h3&gt;

&lt;p&gt;The front-end, or User Interface, is what enable users to interact with the application, call the REST API to trigger the CRUD operations and ultimately interact with the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Back-end
&lt;/h3&gt;

&lt;p&gt;The back-end is what will translate the REST API calls into SQL queries to perform CRUD operations on your database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database
&lt;/h3&gt;

&lt;p&gt;The database is where your data, and where the CRUD operations are ultimately performed via SQL queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Role-Based Access Control Activity logs, ...
&lt;/h3&gt;

&lt;p&gt;In addition to the components listed above, that are the essential components of a CRUD app, additional capabilities are required to build a robust app. Indeed, you might want to restrict which users can perform which operations (for instance deleting the entire database), and log every operations performed for debugging or compliance purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hosting
&lt;/h3&gt;

&lt;p&gt;All the components above have to be hosted somewhere to always be accessible for your and your users.&lt;/p&gt;

&lt;p&gt;Now, let's see different options to build a CRUD app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a CRUD app from scratch
&lt;/h2&gt;

&lt;p&gt;An obvious option to build a CRUD app is to build it from scratch. Most likely, if you're thinking about building such an app, it's because you already have a database storing data you want to enable your users to easily visualise or manipulate. So we will assume you already have an up and running database.&lt;/p&gt;

&lt;p&gt;While CRUD apps seem fairly basic, developing one requires solid front-end, back-end and database knowledge. In this blog, we won't cover everything in detail but list the main steps to build a CRUD app on top of your database, from scratch, and link to useful resources.&lt;/p&gt;

&lt;p&gt;For the sake of the exercise, we'll assume you're using the following popular technologies: &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; for the front-end, &lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt; for the back-end and &lt;a href="https://www.postgresql.org/"&gt;PostreSQL&lt;/a&gt; for your database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build your CRUD app front-end
&lt;/h3&gt;

&lt;p&gt;We used this great tutorial "&lt;a href="https://www.freecodecamp.org/news/how-to-perform-crud-operations-using-react/"&gt;How to Perform CRUD Operations using React, React Hooks, and Axios&lt;/a&gt;" as a reference.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Architecture &amp;amp; design: Let's go. As we're starting from an existing database, you already know what data is stored in this database, and how it is structured. So the first you might do is to think about how you want your users to interact with this data, how you want to represent it, and what will the experience look like.&lt;/li&gt;
&lt;li&gt;  Create your React application&lt;/li&gt;
&lt;li&gt;  Install the Semantic UI Package for React
This package is an UI library providing pre-built components such as buttons, tables and much more.&lt;/li&gt;
&lt;li&gt;  Create your app first screen&lt;/li&gt;
&lt;li&gt;  Create your CREATE, READ and UPDATE files for your CREATE, READ and UPDATE component, no need for a new component for DELETE&lt;/li&gt;
&lt;li&gt;  Build the CREATE, READ, UPDATE and DELETE elements, buttons and logic&lt;/li&gt;
&lt;li&gt;  Build the CRUD requests to the API (once you've built the API)&lt;/li&gt;
&lt;li&gt;  Implement forms validation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Build your CRUD app back-end
&lt;/h3&gt;

&lt;p&gt;Once you're done with the front-end, it's time to build what will be the link between the front-end and the database. We used this "&lt;a href="https://glaucia86.medium.com/developing-a-crud-node-js-application-with-postgresql-d25febb1cc4"&gt;Developing a CRUD Node.js Application with PostgreSQL&lt;/a&gt;" guide as a reference.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create your app architecture in Node.js&lt;/li&gt;
&lt;li&gt;  Configure your app and its connection to your PostgreSQL database&lt;/li&gt;
&lt;li&gt;  Create the routes for your CRUD operations, including writing the API endpoints for their respective methods, and their respective logic to query the database&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deploy your CRUD app
&lt;/h3&gt;

&lt;p&gt;As we mentioned previously, you need to host your database, back-end and front-end online if you want you and your users to be able to access it anytime from anywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus points: add Role-Based Access Control
&lt;/h3&gt;

&lt;p&gt;From installing the necessary packages to setting up user authentification (both signup and login) and their front-end manifestations to configuring the rights on the routes, implementing RBAC on your CRUD app adds significant amount of development time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful tools to reduce CRUD app development time
&lt;/h3&gt;

&lt;p&gt;As we've seen, developing a basic CRUD app from scratch can take significant time. Fortunately, there are tools to accelerate this process, especially on the backend part. Tools like &lt;a href="https://hasura.io/"&gt;Hasura&lt;/a&gt; or &lt;a href="https://postgrest.org/en/stable/"&gt;PostgreSQL&lt;/a&gt;, depending on your stack, will automatically create APIs based on your database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a CRUD app with a CRUD app builder
&lt;/h2&gt;

&lt;p&gt;Even with tools like Hasura or PostgreSQL, building a CRUD still takes time. Even more so if you need specific capabilities in addition to CRUD operations. To prevent you from reinventing the wheel every-time you need to enable your users to manipulate and visualise the data stored in your database, tools exist to build CRUD apps in minute and allow you to focus on adding advanced logic and functionalities to your applications. Examples include &lt;a href="https://blog.forestadmin.com/forest-admin-vs-django-admin/"&gt;&lt;/a&gt;&lt;a href="https://docs.djangoproject.com/en/4.0/ref/contrib/admin/"&gt;Django Admin&lt;/a&gt; or &lt;a href="https://blog.forestadmin.com/forest-admin-vs-laravel-nova/"&gt;&lt;/a&gt;&lt;a href="https://nova.laravel.com/"&gt;Laravel Nova&lt;/a&gt; depending on your stack.&lt;/p&gt;

&lt;p&gt;In this blog, we'll see how to build a CRUD app with &lt;a href="https://www.forestadmin.com/"&gt;Forest Admin&lt;/a&gt;. We'll assume you're building a CRUD app for a &lt;a href="https://blog.forestadmin.com/postgresql-cheat-sheet/"&gt;PostgreSQL&lt;/a&gt; database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install your CRUD app builder
&lt;/h3&gt;

&lt;p&gt;The first step is to install the tool that will help your generate your CRUD app. Using our example Forest Admin with a PostgreSQL database, it only takes a few steps:&lt;/p&gt;

&lt;p&gt;Install Forest Admin CLI&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install -g lumber-cli@latest -s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Login to Forest CLI&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;Generate the backend application&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ forest projects:create "CRUDapp" --databaseConnectionURL "postgres://root:password@localhost:5432/myDatabase" --databaseSchema "public" --applicationHost "localhost" --applicationPort "3310"  
$ cd "CRUDapp" 
$ npm install -s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Run your backend application&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm start&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Build your CRUD app&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;The catch is that with Forest Admin, you get an up and running CRUD app right after installing it on top of your database. It automatically generates visualisations of your tables, CRUD operations and more, as well as the associated front-end.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--55B2sxFX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--55B2sxFX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-1.amazonaws.com/blog.forestadmin.com/2022/05/image-1.png" alt="CRUD app" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You also benefit from built-in Role-Based Access Control, Activity logs and more so you can focus on coding your own business logic, adding custom actions to your new app and customising it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.forestadmin.com/"&gt;Click here&lt;/a&gt; to learn more about Forest Admin, &lt;a href="https://docs.forestadmin.com/documentation/"&gt;read the doc&lt;/a&gt; or &lt;a href="https://app.forestadmin.com/signup"&gt;get started now&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>database</category>
    </item>
    <item>
      <title>PostgreSQL Cheat Sheet</title>
      <dc:creator>Matthieu Blandineau</dc:creator>
      <pubDate>Wed, 11 May 2022 08:41:13 +0000</pubDate>
      <link>https://dev.to/forestadmin/postgresql-cheat-sheet-38j3</link>
      <guid>https://dev.to/forestadmin/postgresql-cheat-sheet-38j3</guid>
      <description>&lt;p&gt;We gathered a list of handy PostgreSQL commands and queries when working with PostgreSQL databases. Please ping us &lt;a href="https://twitter.com/ForestAdmin"&gt;@ForestAdmin&lt;/a&gt; if you’d like to add something to the cheat sheet!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with PostgreSQL
&lt;/h2&gt;

&lt;p&gt;Login and enter PostgreSQL command line utility psql&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo su - postgres psql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List postgres databases&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Connect to postgres database&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Exit postgreSQL command line utility psql&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Managing PostgreSQL
&lt;/h2&gt;

&lt;p&gt;Check PostgreSQL version&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT version();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check if PostgreSQL is installed&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Check if PostgreSQL is running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pgrep -fa -- -D | grep postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart PostgreSQL on Linux&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# systemctl restart postgresql
// or
# service postgresql restart
// or
# /etc/init.d/postgresql restart
// or
# /sbin/service postgresql restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart PostgreSQL on OSX&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# brew services restart postgres
// or
# pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart PostgreSQL on Windows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Winkey + R
Type "services.msc"
Click "restart"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change PostgreSQL user password&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo -u postgres psql
\password postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit from psql&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Interacting with databases in PostgreSQL
&lt;/h2&gt;

&lt;p&gt;List postgres databases&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Connect or switch to postgres database&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Create new postgres database&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Delete postgres database&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Rename postgres database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER DATABASE old_databaseName TO new_databaseName
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Query postgres JSON data&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT *
FROM mytable
WHERE myfield @&amp;gt; '{"key1":"valueA"}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Interacting with tables in PostgreSQL
&lt;/h2&gt;

&lt;p&gt;List postgres tables&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Describe postgres table&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Create postgres table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE tableName( 
    columnName columnType,
    columnName columnType
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delete postgres table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DROP TABLE tableName CASCADE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backup and restore PostgreSQL database
&lt;/h2&gt;

&lt;p&gt;Backup postgres database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pg_dump -d databaseName -U userName &amp;gt; backupFile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restore postgres database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psql databaseName &amp;lt; backupFile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Managing roles and permissions in PostgreSQL
&lt;/h2&gt;

&lt;p&gt;List postgres roles&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT rolname FROM pg_roles;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create postgres user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE USER userName WITH PASSWORD 'userPassword';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delete postgres user&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Change postgres user password&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER ROLE userName WITH PASSWORD 'userPassword';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List all assigned roles postgres&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
    r.rolname,
    r.rolsuper,
    r.rolinherit,
    r.rolcreaterole,
    r.rolcreatedb,
    r.rolcanlogin,
    r.rolconnlimit,
    r.rolvaliduntil,
    ARRAY(SELECT b.rolname
        FROM pg_catalog.pg_auth_members m
        JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
        WHERE m.member = r.oid) as memberof,
    r.rolreplication
FROM pg_catalog.pg_roles r
ORDER BY 1;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grant all permissions on postgres database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRANT ALL PRIVILEGES ON DATABASE databaseName TO userName;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grant connection permissions on postgres database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRANT CONNECT ON DATABASE databaseName TO userName;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List permissions for specific role postgres&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT table_catalog, table_schema, table_name, privilege_type
FROM   information_schema.table_privileges
WHERE  grantee = userName ORDER BY table_name;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ProstgreSQL psql commands recap
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;\?&lt;/code&gt; List all available psql commands&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\h COMMAND&lt;/code&gt; Get help on specific command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\l&lt;/code&gt; List databases&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\c&lt;/code&gt; databaseName Connect to database&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\dt&lt;/code&gt; List tables&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\d&lt;/code&gt; tableName Describe table&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\d+&lt;/code&gt; tableName Describe table with details&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\dn&lt;/code&gt; List schemas&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\df&lt;/code&gt; List functions&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\dv&lt;/code&gt; List views&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\du&lt;/code&gt; List users&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\dy&lt;/code&gt; List events&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\di&lt;/code&gt; List indexes&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\q&lt;/code&gt; Exit&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Need to build admin panels or a GUI tool for PostgreSQL? Check out &lt;a href="https://www.forestadmin.com/integrations/postgresql?utm_source=referral&amp;amp;utm_medium=devto&amp;amp;utm_campaign=cheat-sheet-postgresql&amp;amp;utm_content=cheat-sheet-postgresql"&gt;Forest Admin for PostgreSQ&lt;/a&gt;L&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>High-level architecture of a hybrid SaaS solution</title>
      <dc:creator>Matthieu Blandineau</dc:creator>
      <pubDate>Tue, 10 May 2022 09:12:13 +0000</pubDate>
      <link>https://dev.to/forestadmin/high-level-architecture-of-a-hybrid-saas-solution-386l</link>
      <guid>https://dev.to/forestadmin/high-level-architecture-of-a-hybrid-saas-solution-386l</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Forest Admin is a tool that automatically generates admin panels on top of your database, that can then be customised. Because of the privacy and security requirements most developers and organisations rightfully have over their data, we had to build our solution in a way that ensured those requirements were respected in order to provide a viable offer. That's why we decided to go with a hybrid SaaS architecture.&lt;/p&gt;

&lt;p&gt;We define a hybrid SaaS solution as a software relying simultaneously on a SaaS part and an on-premise part. The SaaS part is hosted and managed by the vendor, and includes the user interface the users will connect to and interact with via their browser. The on-premise (or self-hosted) part is managed and hosted by the user, and includes the users' data and the vendor provided elements to send and receive the relevant data to and from the user interface.&lt;/p&gt;

&lt;p&gt;As discussed in the first paragraph, the main advantage of such an architecture is that the user's data will never be seen by the vendor, and stays within the user's controlled environment. In addition, the user will automatically benefits from updates introduced by the vendor just like with any SaaS solution.&lt;/p&gt;

&lt;p&gt;Let's detail this hybrid SaaS architecture, using Forest Admin as an example.&lt;/p&gt;

&lt;h2&gt;
  
  
  High level hybrid SaaS architecture
&lt;/h2&gt;

&lt;p&gt;In Forest Admin's case, the whole architecture consists of 4 different components as shown below. The user's database, the admin backend, the Forest Admin API server and the Forest Admin UI server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--chARBWoE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mceag9e7id6drxhq2nvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--chARBWoE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mceag9e7id6drxhq2nvl.png" alt="High level hybrid SaaS architecture" width="880" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The user's database
&lt;/h3&gt;

&lt;p&gt;The user's database will be the main data source for Forest Admin to generate admin panels, and feed them.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Forest admin backend
&lt;/h3&gt;

&lt;p&gt;When a user installs Forest Admin, they generate a node.js application on their local machine. It includes a RESTful API that connects to their database. We call this app the admin backend. It feeds all the data to your admin panel interface.&lt;/p&gt;

&lt;p&gt;What it does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it translates client requests (from the end user browser) into queries to the user's database.&lt;/li&gt;
&lt;li&gt;it also provides the Forest Admin API Server with the information needed to build the User Interface. This information includes table names, column names and types, and relationships.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A JSON file called the forestadmin-schema.json carries this metadata within the admin backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Forest Admin API server
&lt;/h3&gt;

&lt;p&gt;The Forest Admin API Server stores the information to build the user interface. This includes both the database structure (sent by the admin backend) and the UI customization made by the user.&lt;/p&gt;

&lt;p&gt;To get more technical, the information stored includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Display &amp;amp; Order — Which tables and columns should be displayed or hidden? In what order should the columns appear in the ‘Table’ view?&lt;/li&gt;
&lt;li&gt;Collection Settings (permissions) — Are the records in this table read-only? Can they be deleted? Can they be exported in a .csv file?&lt;/li&gt;
&lt;li&gt;Widget preferences — Which UI component should be rendered for each column (e.g a file viewer for a column that contains images urls).&lt;/li&gt;
&lt;li&gt;Chart configurations — How are the dashboard charts configured and in which position should they appear?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Forest Admin API Server also manages the Forest Admin app’s logic like user authentication or billing.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Forest Admin UI server
&lt;/h3&gt;

&lt;p&gt;The Forest Admin UI server stores static assets. These include HTML documents, CSS stylesheets and JS script files. It provides the UI components needed to build the interface that displays the data.&lt;/p&gt;

&lt;p&gt;Now that you have a high level overview of the architecture, let's see how the different components interact together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interactions between the different components
&lt;/h2&gt;

&lt;p&gt;Let's go through the http calls made between each of the above-mentioned elements when operating a Forest Admin project. Namely calls made:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;between the end user’s browser and the Forest Admin servers (both UI and API servers),&lt;/li&gt;
&lt;li&gt;between the end user’s browser and the admin backend,&lt;/li&gt;
&lt;li&gt;between the admin backend and the Forest Admin API servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Calls made from the user’s browser
&lt;/h3&gt;

&lt;p&gt;The following lists the calls made by the browser when an end user accesses the admin panel from their browser (at app.forestadmin.com).&lt;/p&gt;

&lt;h4&gt;
  
  
  To the Forest Admin UI servers
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W9JzJxZz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n501q1j9vdmms7xh33jf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W9JzJxZz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n501q1j9vdmms7xh33jf.png" alt="Calls from the user's browser to the Forest Admin UI servers" width="880" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Calls need to go out to the Forest Admin UI server to fetch static assets including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML documents&lt;/li&gt;
&lt;li&gt;CSS stylesheets&lt;/li&gt;
&lt;li&gt;JS scripts&lt;/li&gt;
&lt;li&gt;A map of the assets&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  To the Forest Admin API servers
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qfyIl0fB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hn1eur29wdmb4qmihvqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qfyIl0fB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hn1eur29wdmb4qmihvqu.png" alt="Calls from the user's browser to the Forest Admin API servers" width="880" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Calls need to go out to the Forest Admin API servers to retrieve information regarding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the end user logged in,&lt;/li&gt;
&lt;li&gt;the project they're logged into,&lt;/li&gt;
&lt;li&gt;the environment they're logged into,&lt;/li&gt;
&lt;li&gt;the configuration of the rendering to be displayed (i.e. the configuration of the UI),&lt;/li&gt;
&lt;li&gt;the widgets configuration,&lt;/li&gt;
&lt;li&gt;the billings info of the project,&lt;/li&gt;
&lt;li&gt;any updates happening on the UI configuration. This is done through websockets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  To the admin backend
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0rfyBmTd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k7op2agnjtrh7pfuj83u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0rfyBmTd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k7op2agnjtrh7pfuj83u.png" alt="Calls from the user's browser to the admin backend" width="880" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Calls need to go out to the admin backend to retrieve/ modify data from the database including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET calls to retrieve a list of records, the count of a list or the details of record,&lt;/li&gt;
&lt;li&gt;PUT calls to modify a record,&lt;/li&gt;
&lt;li&gt;POST calls to create a new record or trigger a custom action,&lt;/li&gt;
&lt;li&gt;DELETE calls to delete records.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Calls made from the admin backend
&lt;/h3&gt;

&lt;h4&gt;
  
  
  To the database
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DY-N_jYM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmw5paxgubhzd3zdaey8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DY-N_jYM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmw5paxgubhzd3zdaey8.png" alt="Calls made from the admin backend to the database" width="880" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When calls are made from the browser to the admin backend, the latter translates the call into a database query.&lt;/p&gt;

&lt;h4&gt;
  
  
  To the Forest Admin API servers
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bZK-Sqm9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8gp3rzl19vk2tdkhzhk5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bZK-Sqm9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8gp3rzl19vk2tdkhzhk5.png" alt="Calls made from the admin backend to the forest admin api servers" width="880" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to ensure that the UI reflects the structure of the database, the admin backend needs to send calls containing the information from the forestadmin-schema.json to the Forest Admin API servers. This file is sent upon every restart of the admin backend server.&lt;/p&gt;

&lt;p&gt;At the startup of the admin backend and periodically afterwards, calls are also made to the Forest Admin API servers to retrieve permissions. This protects the data from being accessed by unauthorized users through curl requests for example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Flexibility and extensibility
&lt;/h3&gt;

&lt;p&gt;Because part of the solution's logic resides in the user's systems — the admin backend in Forest Admin's example, the vendor can allow users to customise and extend its solution like they would with any other app, by open sourcing and documenting its on-premise component. &lt;/p&gt;

&lt;h3&gt;
  
  
  Development workflow, CI/CD and hosting
&lt;/h3&gt;

&lt;p&gt;If the vendor open sources its on-premise component, it also allows the user to manage the code of this component in Git, the containerize the back-end app using Docker or Kubernetes, and to deploy it wherever the user sees fit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updates
&lt;/h3&gt;

&lt;p&gt;With this hybrid SaaS architecture, users will benefit from continuous updates to the SaaS part — in Forest Admin's case the UI — by simply refreshing they browser tab. &lt;/p&gt;

&lt;p&gt;For the on-premise part, the downside is that updates do require the user to install updates on their side, and potentially setup tests to make sure updates do not introduce regressions on their specific configuration. &lt;/p&gt;

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

&lt;p&gt;From introducing large updates to managing users' authentication to optimising for performance when you don't host part of your solution, building Forest Admin with this hybrid SaaS architecture introduced various technical challenges of their own, that we plan to cover in more detailed posts in the future. Ping us &lt;a href="https://twitter.com/ForestAdmin"&gt;@ForestAdmin&lt;/a&gt; to let us know what you'd like us to cover first.&lt;/p&gt;




&lt;p&gt;Interest in Forest Admin? Learn more on our &lt;a href="https://www.forestadmin.com?utm_source=referral&amp;amp;utm_medium=devto&amp;amp;utm_campaign=blog-architecture&amp;amp;utm_content=blog-architecture"&gt;website&lt;/a&gt; or our &lt;a href="https://docs.forestadmin.com/documentation/"&gt;doc&lt;/a&gt;, or &lt;a href="https://app.forestadmin.com/signup?utm_source=referral&amp;amp;utm_medium=devto&amp;amp;utm_campaign=blog-architecture&amp;amp;utm_content=blog-architecture"&gt;sign up here&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>architecture</category>
      <category>programming</category>
      <category>database</category>
    </item>
  </channel>
</rss>
