<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>home of ogirginc</title><description>Welcome (. ❛ ᴗ ❛.)</description><link>https://churchtao.github.io/</link><item><title>How to fix a mismatch between psql and server?</title><link>https://churchtao.github.io/archive/240222-psql-server-mismatch/</link><guid isPermaLink="true">https://churchtao.github.io/archive/240222-psql-server-mismatch/</guid><description>Fix running different versions of psql and the Postgresql.</description><pubDate>Thu, 22 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You have installed a new Postgresql with Homebrew, but whenever you type &lt;code&gt;psql&lt;/code&gt;, you get a warning like below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; psql
psql (14.11 (Homebrew), server 16.2 (Homebrew))
WARNING: psql major version 14, server major version 16.
         Some psql features might not work.
Type &quot;help&quot; for help.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This happens because when you install a new version of Postgresql, Homebrew still uses the old version even after you have to stop the old version of Postgresql through the &lt;code&gt;brew services stop&lt;/code&gt; command. We can confirm it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; brew link postgresql@16
Linking /opt/homebrew/Cellar/postgresql@16/16.2...
Error: Could not symlink bin/clusterdb
Target /opt/homebrew/bin/clusterdb
is a symlink belonging to postgresql@14. You can unlink it:
  brew unlink postgresql@14

To force the link and overwrite all conflicting files:
  brew link --overwrite postgresql@16

To list all files that would be deleted:
  brew link --overwrite postgresql@16 --dry-run
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To fix this, you need to explicitly tell Homebrew to stop using the old version and start using the new version.&lt;/p&gt;
&lt;p&gt;First, use &lt;code&gt;unlink&lt;/code&gt; to stop using the old version:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; brew unlink postgresql@14
Unlinking /opt/homebrew/Cellar/postgresql@14/14.11... 334 symlinks removed.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Second, use &lt;code&gt;link&lt;/code&gt; to start using the new version:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; brew link postgresql@16
Linking /opt/homebrew/Cellar/postgresql@16/16.2... 811 symlinks created.

If you need to have this software first in your PATH instead consider running:
  echo &apos;export PATH=&quot;/opt/homebrew/opt/postgresql@16/bin:$PATH&quot;&apos; &amp;gt;&amp;gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After these two, you can check to see if it’s fixed or not:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; psql --version
psql (PostgreSQL) 16.2 (Homebrew)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fixed! 🎉&lt;/p&gt;
</content:encoded></item><item><title>How to install multiple Postgresql versions on macOS?</title><link>https://churchtao.github.io/archive/210105-multiple-postgresql-versions-macos/</link><guid isPermaLink="true">https://churchtao.github.io/archive/210105-multiple-postgresql-versions-macos/</guid><description>Install different versions of Postgresql on your Mac with Homebrew.</description><pubDate>Tue, 05 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;So, you have decided to have multiple Postgresql versions on your Mac. Lucky for you, I have tried all options I was able to find and decided &lt;a href=&quot;https://github.com/petere&quot;&gt;Peter Eisentraut&lt;/a&gt;’s &lt;a href=&quot;https://github.com/petere/postgresql-common&quot;&gt;Postgresql Common package&lt;/a&gt;, which is a Postgresql database cluster manager for Postgresql.&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;What is a database cluster?&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;A database cluster is a bit of an ambiguous term. Its definition varies depending on the context. In this article, I am not going to explain what it means in production. On local machines, it is a collection of databases that are managed by a single database server. Clusters allow us to install multiple versions of Postgresql on our macOS. To manage these clusters, we will be using a package called Postgresql Common.&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;Postgresql Common with Homebrew&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;First, we will install the Postgresql Common &lt;a href=&quot;https://github.com/petere/homebrew-postgresql&quot;&gt;formulae&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew install petere/postgresql/postgresql-common
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With these formulae installed, we can have multiple versions of PostgreSQL in parallel. We should be able to install any version of Postgresql starting with version 8.3. If you do want to check the available versions, use the Homebrew’s &lt;code&gt;search&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew search petere/postgresql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or you check the Github repo to see the available version on your browser: &lt;a href=&quot;https://github.com/petere/homebrew-postgresql&quot;&gt;https://github.com/petere/homebrew-postgresql&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If I wanted to install the version 12, this is how I would do it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew install petere/postgresql/postgresql@12
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command will fetch the latest minor version of the provided major version. For example, if there are 4 minor versions available, we would have version 12.4 installed automatically. Depending on your internet speed, it should not take more than a couple of minutes to download. Same goes for installing it with the &lt;code&gt;make&lt;/code&gt; command, which depends on how fast the computer is.&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;Creating a cluster for the first time&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;To create a cluster, we will be using the &lt;code&gt;pg_createcluster&lt;/code&gt; wrapper scripts. These scripts are just wrappers around &lt;code&gt;pg_ctl&lt;/code&gt; and &lt;code&gt;initdb&lt;/code&gt; to make managing easier. Now, let&apos;s create our first cluster. We will name this one as the &lt;code&gt;main&lt;/code&gt; but you can choose whatever name you like.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pg_createcluster 12 main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have created a new cluster named &lt;code&gt;main&lt;/code&gt; which is version 12.4. If you like, we can check the status of the cluster with the &lt;code&gt;pg_lsclusters&lt;/code&gt; wrapper script.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pg_lsclusters
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should list all the clusters, with some additional information, we have created in our machine.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Ver Cluster Port Status Owner    Data directory                        Log file
12  main    5432 down   ogirginc /usr/local/var/lib/postgresql/12/main /usr/local/var/log/postgresql/postgresql-12-main.log
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&apos;s start our newly created cluster, we will be using &lt;code&gt;pg_ctlcluster&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pg_ctlcluster 12 main start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just to be sure, check the &lt;code&gt;Status&lt;/code&gt; with &lt;code&gt;pg_lsclusters&lt;/code&gt;. You should see the word &lt;code&gt;down&lt;/code&gt; being replaced with &lt;code&gt;online&lt;/code&gt;. Also, the output colour change might change depending on your theme. In my case, it was red turned to green.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Ver Cluster Port Status Owner    Data directory                        Log file
12  main    5432 online ogirginc /usr/local/var/lib/postgresql/12/main /usr/local/var/log/postgresql/postgresql-12-main.log
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After starting your cluster, rest is the same with any Postgresql installation. Create a database with &lt;code&gt;created&lt;/code&gt; command and list those with &lt;code&gt;psql -c &apos;\l&apos;&lt;/code&gt; command to check if all is good. You should do something similar to this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;List of databases
   Name    |  Owner   | Encoding |   Collate   | Ctype |   Access privileges
-----------+----------+----------+-------------+-------+-----------------------
 ogirginc  | ogirginc | UTF8     | en_US.UTF-8 | UTF-8 |
 postgres  | ogirginc | UTF8     | en_US.UTF-8 | UTF-8 |
 template0 | ogirginc | UTF8     | en_US.UTF-8 | UTF-8 | =c/ogirginc          +
           |          |          |             |       | ogirginc=CTc/ogirginc
 template1 | ogirginc | UTF8     | en_US.UTF-8 | UTF-8 | =c/ogirginc          +
           |          |          |             |       | ogirginc=CTc/ogirginc
(4 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s it! Now just repeat the process for each version you want to install, and it should work with a problem. If you do encounter any problems, check the Troubleshooting section below. If the problem still continues, feel free to open an issue and I would try my best to help!&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/h1&gt;
&lt;h2&gt;&lt;strong&gt;Authentication failed for user&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The default Postgres configuration sets the client authentication method to &lt;code&gt;peer&lt;/code&gt; or &lt;code&gt;md5&lt;/code&gt;, which can prevent connection to the database.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Run &lt;code&gt;psql -c &apos;show hba_file;&apos;&lt;/code&gt; to get &lt;code&gt;pg_hba.conf&lt;/code&gt;’s path. The output should look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hba_file
-----------------------------------------------
 /usr/local/etc/postgresql/12/main/pg_hba.conf
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open the &lt;code&gt;pg_hba.conf&lt;/code&gt; file with your editor and go to the end of it, where we can see the preferred authentication methods. If you don’t have any sensitive data and your local database is not accessible through the internet, I would suggest changing the &lt;code&gt;METHOD&lt;/code&gt; to &lt;code&gt;trust&lt;/code&gt; for ease of use. This is how I use it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Database administrative login by Unix domain socket
local   all             ogirginc                                trust

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# &quot;local&quot; is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            md5
host    replication     all             ::1/128                 md5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&lt;strong&gt;No such file or directory&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;When creating a cluster, &lt;code&gt;pg_ctl&lt;/code&gt; fails to find &lt;code&gt;conf.d&lt;/code&gt; because it is missing. It’s a known bug. Check &lt;a href=&quot;https://github.com/petere/homebrew-postgresql/issues/45&quot;&gt;#45&lt;/a&gt; and &lt;a href=&quot;https://github.com/petere/homebrew-postgresql/issues/49&quot;&gt;#49&lt;/a&gt; for additional details.&lt;/p&gt;
&lt;p&gt;Example output of &lt;code&gt;pg_ctlcluster 12 main start&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Error: /usr/local/opt/postgresql@12/bin/pg_ctl /usr/local/opt/postgresql@12/bin/pg_ctl start -D /usr/local/var/lib/postgresql/12/main -l /usr/local/var/log/postgresql/postgresql-12-main.log -s -o  -c config_file=&quot;/usr/local/etc/postgresql/12/main/postgresql.conf&quot; -c external_pid_file=&quot;/usr/local/var/run/postgresql/12-main.pid&quot;  exited with status 1:
2020-07-13 10:32:51.376 GMT [9841] LOG:  could not open configuration directory &quot;/usr/local/etc/postgresql/12/main/conf.d&quot;: No such file or directory
2020-07-13 10:32:51.376 GMT [9841] FATAL:  configuration file &quot;/usr/local/etc/postgresql/12/main/postgresql.conf&quot; contains errors
pg_ctl: could not start server
Examine the log output.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Create the &lt;code&gt;conf.d&lt;/code&gt; with the &lt;code&gt;mkdir&lt;/code&gt; command.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir /usr/local/etc/postgresql/12/main/conf.d
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;Perl required&lt;/strong&gt;&lt;/h3&gt;
&lt;h2&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;You get the error below because the required Perl files could not be found. Check &lt;a href=&quot;https://github.com/petere/homebrew-postgresql/issues/44#issuecomment-570881749&quot;&gt;#44&lt;/a&gt; for additional details.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;configure: error: header file &amp;lt;perl.h&amp;gt; is required for Perl
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Try installing Xcode, which should install all necessary Perl files and specify the Xcode that you wish to use for command line developer tools like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo xcode-select --switch /Applications/Xcode.app/
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&lt;strong&gt;LANG error&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;For some unknown reasons, the operating system’s locales are messed up.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;First export the desired language and then create the cluster. An example for &lt;code&gt;en_US&lt;/code&gt; would be like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export LANG=en_US.UTF-8
pg_createcluster 12 main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, I would highly recommend fixing the locales as it might cause additional non-database related problems.&lt;/p&gt;
&lt;h2&gt;Different versions for &lt;code&gt;psql&lt;/code&gt; and &lt;code&gt;server&lt;/code&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;You have installed multiple Postgresql versions with Homebrew and &lt;code&gt;psql&lt;/code&gt; automatically picks the latest version.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;When trying to use &lt;code&gt;psql&lt;/code&gt; with an earlier version of a Postgresql, a warning will be presented.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;psql (13.0 (Homebrew petere/postgresql), server 12.4 (Homebrew petere/postgresql))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First of all, this is just a warning. Secondly, most, if not all things, should work in &lt;code&gt;psql&lt;/code&gt;. However, tools like &lt;code&gt;pg_dump&lt;/code&gt; might fail. To fix when you get this warning, export the desired Postgresql version to the path.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export PATH=&quot;/usr/local/opt/postgresql@12/bin:$PATH&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When retrying, there should not be any warning about version mismatch.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;❯ psql
psql (12.4 (Homebrew petere/postgresql))
Type &quot;help&quot; for help.
ogirginc=*#*
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&lt;strong&gt;Create a database with a different port&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;When you create a new cluster, Postgresql assigns the next available port number to this new cluster, which results in not being able to connect to the default 5432 port. An example of an error, while trying to run &lt;code&gt;psql&lt;/code&gt; for the newly created second cluster:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;psql: error: could not connect to server: could not connect to server: No such file or directory
	Is the server running locally and accepting
	connections on Unix domain socket &quot;/tmp/.s.PGSQL.5432&quot;?
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;To fix this connection error, we have to specifically tell &lt;code&gt;psql&lt;/code&gt; which port it should use to connect to the database by exporting the &lt;code&gt;PGPORT&lt;/code&gt; environment variable. Check with the &lt;code&gt;pg_lsclusters&lt;/code&gt; wrapper script to which port do you need to connect the database.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Ver Cluster Port Status Owner    Data directory                        Log file
12  main    5433 online ogirginc /usr/local/var/lib/postgresql/12/main /usr/local/var/log/postgresql/postgresql-12-main.log
13  main    5432 down   ogirginc /usr/local/var/lib/postgresql/13/main /usr/local/var/log/postgresql/postgresql-13-main.log
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To use version 12, I need to set &lt;code&gt;PGPORT&lt;/code&gt; to &lt;code&gt;5433&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export PGPORT=5433
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this explicit port setting, we can use &lt;code&gt;psql&lt;/code&gt; or any other Postgresql utilities without any problems.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;psql (12.4 (Homebrew petere/postgresql))
Type &quot;help&quot; for help.
ogirginc=*#*
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&lt;strong&gt;You call this simple?&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;I am fully aware it is not simple nor easy, but it gets the job done.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Try your luck with &lt;a href=&quot;https://postgresapp.com/&quot;&gt;Postgres.app&lt;/a&gt;. Maybe, it will work for you. :)&lt;/p&gt;
</content:encoded></item><item><title>Using PRIMARY KEY in PostgreSQL&apos;s GROUP BY</title><link>https://churchtao.github.io/archive/250323-pg-group-by-with-functional-dependency/</link><guid isPermaLink="true">https://churchtao.github.io/archive/250323-pg-group-by-with-functional-dependency/</guid><description>Understand why having a primary key in the GROUP BY clause allows selecting non-aggregated columns without including them in the GROUP BY clause.</description><pubDate>Sun, 23 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Have you noticed that in some cases, PostgreSQL does not ask you to include the selected column in the &lt;code&gt;GROUP BY&lt;/code&gt; clause?&lt;/p&gt;
&lt;p&gt;Until recently, I haven&apos;t spent time on understanding why this happens. Turns out, there is a simple explanation. Compared to the standard SQL, PostgreSQL actually has a special handling for the &lt;code&gt;GROUP BY&lt;/code&gt; clause. So, what happens here is, when a &lt;code&gt;PRIMARY KEY&lt;/code&gt; is included in a &lt;code&gt;GROUP BY&lt;/code&gt; clause, it actually changes how the clause works, which allows selecting non-aggregated columns without including them in the &lt;code&gt;GROUP BY&lt;/code&gt; clause.&lt;/p&gt;
&lt;p&gt;Let&apos;s dive into this a bit more.&lt;/p&gt;
&lt;h2&gt;The Standard SQL Expectation&lt;/h2&gt;
&lt;p&gt;In standard SQL, the rule is clear! If you&apos;re using a &lt;code&gt;GROUP BY&lt;/code&gt; clause, every column in your &lt;code&gt;SELECT&lt;/code&gt; statement must either:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Be included in the &lt;code&gt;GROUP BY&lt;/code&gt; clause, or&lt;/li&gt;
&lt;li&gt;Be used within an aggregate function (like &lt;code&gt;SUM&lt;/code&gt;, &lt;code&gt;COUNT&lt;/code&gt;, &lt;code&gt;MAX&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And you know, this does make sense – if you&apos;re grouping rows together, the database needs to know which value to display for a column that might have different values within the group.&lt;/p&gt;
&lt;p&gt;However, things are a bit different in the land of PostgreSQL.&lt;/p&gt;
&lt;h1&gt;PostgreSQL&apos;s Special Handling&lt;/h1&gt;
&lt;p&gt;Check this simplified example of what I was working on recently:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
  users.id,
  users.full_name,
  users.time_zone,
  message_checkins.created_at::date AS checkin_date,
  COUNT(*) as check_count
FROM
  message_checkins
JOIN
  users ON message_checkins.user_id = users.id
GROUP BY
  users.id, users.full_name, checkin_date
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that I am selecting &lt;code&gt;users.time_zone&lt;/code&gt;, but it&apos;s not in the &lt;code&gt;GROUP BY&lt;/code&gt; clause. Turns out, in many database systems, this would cause an error. However, in PostgreSQL, this works perfectly fine.&lt;/p&gt;
&lt;p&gt;OK, that&apos;s great, but why??&lt;/p&gt;
&lt;h2&gt;Functional Dependencies to the Rescue&lt;/h2&gt;
&lt;p&gt;PostgreSQL implements a concept called &quot;functional dependency&quot;, which is not a very self-explanatory name if you ask me. If you want to get even more confused, you can read the &lt;a href=&quot;https://www.postgresql.org/docs/17/sql-select.html#SQL-GROUPBY&quot;&gt;official documentation&lt;/a&gt; on this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When GROUP BY is present, or any aggregate functions are present, it is not valid for the SELECT list expressions to refer to ungrouped columns except within aggregate functions or when the ungrouped column is functionally dependent on the grouped columns, since there would otherwise be more than one possible value to return for an ungrouped column. A functional dependency exists if the grouped columns (or a subset thereof) are the primary key of the table containing the ungrouped column.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my own simplified terms; if you have a &lt;code&gt;PRIMARY KEY&lt;/code&gt; in your &lt;code&gt;GROUP BY&lt;/code&gt; clause, you can &lt;code&gt;select&lt;/code&gt; any column from the same table without including it in the &lt;code&gt;GROUP BY&lt;/code&gt; clause.&lt;/p&gt;
&lt;p&gt;To get back to my example above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;users.id&lt;/code&gt; is the primary key for the &lt;code&gt;users&lt;/code&gt; table.&lt;/li&gt;
&lt;li&gt;For any specific &lt;code&gt;users.id&lt;/code&gt;, there is exactly one corresponding &lt;code&gt;users.time_zone&lt;/code&gt; value.&lt;/li&gt;
&lt;li&gt;Therefore, &lt;code&gt;users.time_zone&lt;/code&gt; is functionally dependent on &lt;code&gt;users.id&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since we&apos;re grouping by &lt;code&gt;users.id&lt;/code&gt;, PostgreSQL knows that all rows with the same &lt;code&gt;users.id&lt;/code&gt; will also have the same &lt;code&gt;users.time_zone&lt;/code&gt;, so it doesn&apos;t require you to include it in the &lt;code&gt;GROUP BY&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Database Portability&lt;/h2&gt;
&lt;p&gt;Ha. Ha. When is the last time this was a real issue for you? Be honest.&lt;/p&gt;
&lt;h2&gt;Performance Implications&lt;/h2&gt;
&lt;p&gt;Sure, taking advantage of PostgreSQL&apos;s functional dependency understanding can make queries more concise, especially for complex queries with many columns. However, it&apos;s worth noting that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The query optimizer needs to verify these functional dependencies.&lt;/li&gt;
&lt;li&gt;For very complex queries, explicitly listing all columns might help the query planner.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To conclude, unless you&apos;re working with very large datasets or very complex queries, you shouldn&apos;t notice a significant difference in performance – probably.&lt;/p&gt;
</content:encoded></item><item><title>The &apos;postmaster.pid&apos; already exists</title><link>https://churchtao.github.io/archive/240814-postmaster-pid-exists/</link><guid isPermaLink="true">https://churchtao.github.io/archive/240814-postmaster-pid-exists/</guid><description>Remove the dead &apos;postmaster.pid&apos; for PostgreSQL on macOS.</description><pubDate>Wed, 14 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you&apos;ve encountered the following error message while working with PostgreSQL on an Apple M series machine using Homebrew, you&apos;re not alone:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2024-08-13 08:53:06.060 +03 [64564] FATAL:  lock file &quot;postmaster.pid&quot; already exists
2024-08-13 08:53:06.060 +03 [64564] HINT:  Is another postmaster (PID 773) running in data directory &quot;/opt/homebrew/var/postgresql@16&quot;?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This error typically indicates that there is a lock file named &lt;code&gt;postmaster.pid&lt;/code&gt; already present in the data directory, potentially because another instance of PostgreSQL is running or because a previous instance was not shut down properly.&lt;/p&gt;
&lt;h2&gt;Quick Fix&lt;/h2&gt;
&lt;p&gt;To resolve this issue, you can remove the existing lock file. Use the &lt;code&gt;rm&lt;/code&gt; command to delete the &lt;code&gt;postmaster.pid&lt;/code&gt; file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rm /opt/homebrew/var/postgresql@16/postmaster.pid
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After removing the lock file, you should be able to start PostgreSQL without encountering the &quot;postmaster.pid&quot; error.&lt;/p&gt;
&lt;h2&gt;Why Does This Happen?&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;postmaster.pid&lt;/code&gt; file is created by PostgreSQL to ensure that only one instance of the server is running at a time in a given data directory. If PostgreSQL crashes or is not shut down properly, this file may not be removed, leading to the error when you try to start PostgreSQL again.&lt;/p&gt;
&lt;p&gt;Make sure that no other instance of PostgreSQL is running before doing removing the file, as it could lead to data corruption.&lt;/p&gt;
</content:encoded></item><item><title>Enable relativenumber for neo-tree</title><link>https://churchtao.github.io/archive/241115-neotree-relative-number/</link><guid isPermaLink="true">https://churchtao.github.io/archive/241115-neotree-relative-number/</guid><description>Enable relative line numbers for lazyvim users when the neo-tree buffer becomes active.</description><pubDate>Fri, 15 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you are a lazyvim user and want to enable relative line numbers, first create a file for &lt;code&gt;neo-tree.nvim&lt;/code&gt; if you don’t have already, under the &lt;code&gt;plugins&lt;/code&gt; folder:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return {
  &quot;nvim-neo-tree/neo-tree.nvim&quot;,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we are going to update our config by addin an option with event handler to display relative line numbers when the &lt;code&gt;neo-tree&lt;/code&gt; buffer becomes active:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return {
  &quot;nvim-neo-tree/neo-tree.nvim&quot;,
  opts = {
    event_handlers = {
      {
        event = &quot;neo_tree_buffer_enter&quot;,
        handler = function()
          vim.opt_local.number = true
          vim.opt_local.relativenumber = true
        end,
      },
    },
  },
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, when you open the &lt;code&gt;neo-tree&lt;/code&gt;, you should see the line numbers.&lt;/p&gt;
</content:encoded></item><item><title>Fix SSL error using Heroku’s Redis for Flipper</title><link>https://churchtao.github.io/archive/240704-redis-heroku-ssl-flipper/</link><guid isPermaLink="true">https://churchtao.github.io/archive/240704-redis-heroku-ssl-flipper/</guid><description>Fix the SSL connection error while using Flipper with Heroku’s Redis add-on.</description><pubDate>Thu, 04 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello &lt;strong&gt;&lt;code&gt;Redis::CannotConnectError&lt;/code&gt; 👋&lt;/strong&gt;, my old friend. I did not miss you at all.&lt;/p&gt;
&lt;p&gt;Years later, I once again, got the SSL connection error while I was adding the Flipper gem to our project, which is hosted on Heroku and uses Heroku’s Redis.&lt;/p&gt;
&lt;p&gt;For a quick solution, check this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# frozen_string_literal: true
require &apos;flipper/adapters/redis&apos;

Flipper.configure do |config|
  config.default do
    redis = Redis.new(
      url: ENV.fetch(&apos;REDIS_URL&apos;, nil),
      ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }
    )

    adapter = Flipper::Adapters::Redis.new(redis)
    Flipper.new(adapter)
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to dig deep and understand why it is &lt;strong&gt;safe&lt;/strong&gt; to use “verify none”, you can check the &lt;a href=&quot;How%20to%20solve%20the%20SSL%20error%20for%20Redis%206%20on%20Heroku%20736601888821433680378a1ca1fa96f9.md&quot;&gt;&lt;strong&gt;How to solve the SSL error for Redis 6 on Heroku?&lt;/strong&gt;&lt;/a&gt; article that I wrote years ago.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://www.flippercloud.io/docs/adapters/redis&lt;/li&gt;
&lt;li&gt;https://stackoverflow.com/questions/65834575/how-to-enable-tls-for-redis-6-on-sidekiq&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Show SQL on Ruby on Rails console</title><link>https://churchtao.github.io/archive/241022-rails-console-to-sql/</link><guid isPermaLink="true">https://churchtao.github.io/archive/241022-rails-console-to-sql/</guid><description>Update the ActiveRecord logger to show the SQL queries on the Rails console.</description><pubDate>Tue, 22 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Time to time, I like to test my &lt;code&gt;ActiveRecord&lt;/code&gt; queries on my apps’ consoles. Play it, tweak it. Quite straightforward to do it on a Rails console.&lt;/p&gt;
&lt;p&gt;However, there is a slight problem with this method; you cannot see the generated SQL nor how many milliseconds were spent on this query. To solve it, you need to update the &lt;code&gt;ActiveRecord&lt;/code&gt;’s logger to log the output on standard output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ActiveRecord::Base.logger = Logger.new(STDOUT)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is really all you need. Now, when you run an &lt;code&gt;ActiveRecord&lt;/code&gt; query, you will also get the SQL with load time.&lt;/p&gt;
&lt;p&gt;If you really want to get this every time, which I don’t suggest, update your &lt;code&gt;irbrc&lt;/code&gt; file like below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if defined?(Rails::Console)
  ActiveRecord::Base.logger = Logger.new(STDOUT)
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;FYI, the reason why I don’t suggest is, I don’t always need to see the SQL query while playing around with models. If that’s not the case for you, definitely go for it.&lt;/p&gt;
</content:encoded></item><item><title>How to solve the SSL error for Redis 6 on Heroku?</title><link>https://churchtao.github.io/archive/241122-redis-6-heroku-ssl/</link><guid isPermaLink="true">https://churchtao.github.io/archive/241122-redis-6-heroku-ssl/</guid><description>Fix the SSL connection error while using Redis 6 with Heroku’s Redis add-on.</description><pubDate>Thu, 03 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you try to connect a Ruby on Rails app with a Heroku Redis add-on (excluding the Hobby Dev plan), there is a very high chance for you to get the error below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error:
certificate verify failed (self signed certificate in certificate chain)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;&lt;strong&gt;Reason&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;From version 6 and above, Redis requires using TLS to connect. However, Heroku does not use SSL internally. They terminate SSL at the router level and &lt;a href=&quot;https://devcenter.heroku.com/articles/http-routing#routing&quot;&gt;&lt;strong&gt;forward&lt;/strong&gt;&lt;/a&gt; requests from there to your application via HTTP, which is safe as all these do happen behind Heroku’s firewall. Also, let’s face it, Heroku’s security measures –probably– are better than yours.&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;To fix this, you will need to use &lt;code&gt;OpenSSL::SSL::VERIFY_NONE&lt;/code&gt; for your Redis client.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Redis.new(
  url: &apos;url&apos;,
  driver: :ruby,
  ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you do use Sidekiq, configuration should be done through the Sidekiq initializers:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*# config/initializers/sidekiq.rb*

Sidekiq.configure_server do |config|
  config.redis = { ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }
end

Sidekiq.configure_client do |config|
  config.redis = { ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }
end
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h1&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/h1&gt;
&lt;h2&gt;&lt;strong&gt;No error with Redis 6!?&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Assuming you have double-checked the Redis version, the plan is probably on the Hobby Dev version, which does support both HTTP and HTTPS &lt;a href=&quot;https://devcenter.heroku.com/articles/heroku-redis#create-a-new-instance&quot;&gt;connections&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;For the Hobby Dev plan, you should see two environment variables set under the app’s “Config Vars” section. If you do plan to keep the add-on as Hobby Dev, no change is needed.&lt;/p&gt;
&lt;p&gt;If you do plan to upgrade the add-on to Premium 0 or above, you need to use &lt;code&gt;VERIFY_NONE&lt;/code&gt; as above.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://stackoverflow.com/questions/65834575/how-to-enable-tls-for-redis-6-on-sidekiq&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item></channel></rss>