Problem/Motivation

For PostgreSQL in Drupal 10 will the pg_trgm extension be a requirement. The extension needs to be created. Both must be done by a database user that has at least superuser privileges. The database user that is used by Drupal should not have those privileges. That would be a security risk.

Proposed resolution

Add a hook_requirements() that will throw an warning when the extension is not created. In D10 the warning will be replaced by an error.

How to manual test

Install the patch on a system with a PostgreSQL backend and to to the page "admin/reports/status". When the extension PG_TRGM is created, then there should be no warning. When the extension is not created or is dropped, then the following warning should be displayed: "The pg_trgm extension is not created. This extension is only needed on a PostgreSQL database. Extensions on PostgreSQL can only be created by a database user with superuser privileges. The current warning will be replaced by an error before the release of Drupal 10.0.0."
pg_trgm extension warning

The default command to create the extension is: create extension pg_trgm;. It can be that the additional contrib package for postgresql needs to be installed.
The default command to remove the esxtension is: drop extension pg_trgm;.

Remaining tasks

TBD

User interface changes

None

API changes

New method called Drupal\Core\Database\Driver\pgsql\Schema::extensionExists(string $name). Which returns true when the given extension name is installed and created or return false when that is not the case.

Data model changes

None

Release notes snippet

In preparation for Drupal 10 PostgreSQL requirements, sites running PostgreSQL without the pg_trm extension will begin to see a warning in the status report when it is not installed.

For the committer

Could @mixologic get commit credit for his work on the testbot which makes this patch possible.

CommentFileSizeAuthor
#45 214921-45.patch3.16 KBdaffie
#45 interdiff-3214921-43-45.txt754 bytesdaffie
#43 3214921-43.patch3.23 KBdaffie
#43 interdiff-3214921-39-43.txt2.93 KBdaffie
#39 3214921-39.patch3.5 KBdaffie
#38 3214921-38.patch3.5 KBdaffie
#37 3214921-37.patch3.5 KBdaffie
#37 interdiff-3214921-29-37.txt2.48 KBdaffie
#29 3214921-29.patch2.17 KBdaffie
#29 interdiff-3214921-24-29.txt1.18 KBdaffie
#24 3214921-24.patch2.21 KBdaffie
#24 interdiff-3214921-18-24.txt1.37 KBdaffie
#21 drupal-3214921-cli-core-requirements.png94.35 KBxurizaemon
#21 drupal-3214921-browser-ui-warning.png35.12 KBxurizaemon
#18 3214921-18.patch2.23 KBdaffie
#18 interdiff-3214921-10-18.txt1.07 KBdaffie
#15 3214921-15.patch3.43 KBdaffie
#15 interdiff-3214921-10-15.txt3.34 KBdaffie
#10 3214921-10.patch2.22 KBdaffie
#10 interdiff-3214921-3-10.txt727 bytesdaffie
#9 the pg_trgm extension warning on 9.3.png36.18 KBdaffie
#5 3214921-3.patch2.19 KBdaffie
#5 3214921-3-for-postgresql-96-expected-to-fail.patch2.72 KBdaffie
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

daffie created an issue. See original summary.

daffie’s picture

Issue summary: View changes

Fixed a number of my own typos.

Gábor Hojtsy’s picture

Title: Add a requirements warning when PostgreSQL is used and the pg_trgm extension is not installed or created » Add a requirements warning in Drupal 9 when PostgreSQL is used and the pg_trgm extension is not installed or created
Parent issue: #3190516: [Policy] For PostgreSQL require that the pg_trgm extension is not only installed, but also created. »
Related issues: +#3190516: [Policy] For PostgreSQL require that the pg_trgm extension is not only installed, but also created.

Make target version clear in title, since we want to make a slightly different change in Drupal 10: #3214922: Add a requirements error in Drupal 10 when PostgreSQL is used and the pg_trgm extension is not installed or created.

Gábor Hojtsy’s picture

daffie’s picture

Issue tags: +Needs manual testing
daffie’s picture

Issue summary: View changes
andypost’s picture

Looks great except naming to make it more extendable in future

+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -1060,6 +1060,21 @@ protected function hashBase64($data) {
+   * Determines whether the PostgreSQL extension is created.
...
+  public function extensionExists($name) {

I'd make it more broader - requirementsValid(): bool

Also would be great to mark method @internal

daffie’s picture

Issue summary: View changes
FileSize
36.18 KB
daffie’s picture

An extension is a typical PostgreSQL thing for which we test. We already have in the class Drupal\Core\Database\Schema a number of methods in the same style: tableExists(), fieldExists(), constraintExists() and indexExists(). For me the logical thing to do is to name the new method in the same way.
Which other type would you like to test for with: requirementsValid()?

andypost’s picture

Looks great, I'd just added link to official docs about creation

Taran2L’s picture

hey @daffie,

A few comments:

1. Issue description has this:

The database user that is used by Drupal should not have those privileges. That would be a security risk.

But the proposed patch does not do anything about that. I guess issue description is misleading a bit

2.

Add a hook_requirements() that will throw an warning when the extension is not installed and/or not created. In D10 the warning will be replaced by an error.

The proposed patch checks if the extension is installed (afaik), but says it's not created. I believe it also could be misleading. Either update the message to include all the options (not created, not installed or dropped) OR add more sophisticated checks (if possible) to clearly state what's wrong.

3. Test coverage is missing, but not sure what can be done here. Maybe unit with mocking the DB queries?

daffie’s picture

@Taran2L: Thank you for your review.

For #12.1: Because of it being a security risk, do we not try to install and/or enable the pg_trgm extension. We only test if that has been done.

For #12.2: The problem is that PostgreSQL uses "installed" and "created" not consistently with extensions. PostgreSQL extensions are a bit like Drupal modules. You need to copy the module files to the modules directory and then enable the module. In most linux distributions the pg_trgm extension files are already included in the disto. If not, then you have to "install" the extension files manually or with a package manager. When that is done, you can "install" the extension with the "CREATE EXTENSION 'pg_trgm'" command. See: https://www.postgresql.org/docs/current/sql-createextension.html I have used both "install" and "create" to increase the chance that site owners with a PostgreSQL database end up with the correct fix.

For #12.3: The only way to test this patch is by creating and dropping the extension and see that the warning is there or not depending on the status of the extension. This can only be done manually. You need superuser privileges for crating and dropping extensions.

Taran2L’s picture

@daffie:

#12.2 As far as I can tell, there is also https://www.postgresql.org/docs/current/view-pg-available-extensions.html, so it should be possible to detect whether the extension is available for loading or not => giving us the ability to set a very detailed warning/error message. What do you think?

daffie’s picture

Title: Add a requirements warning in Drupal 9 when PostgreSQL is used and the pg_trgm extension is not installed or created » Add a requirements warning in Drupal 9 when PostgreSQL is used and the pg_trgm extension is not created
Issue summary: View changes
FileSize
3.34 KB
3.43 KB

@taran2L: Again that you for your input. I have added an extra test for the availability of the pg_trgm extension. The warning message now depends on the outcome of the test. I have created a new method in the PostgreSQL Schema class. The method is called Schema::extensionAvailable()

When the extension files are NOT available the warning will be:
"The pg_trgm extension files are not available in the database. Therefor the extension cannot be created. This extension is only needed on a PostgreSQL database. Extensions on PostgreSQL can only be created by a database user with superuser privileges. The current warning will be replaced by an error before the release of Drupal 10.0.0."

When the extension files are available the warning will be:
"The pg_trgm extension is not created. This extension is only needed on a PostgreSQL database. Extensions on PostgreSQL can only be created by a database user with superuser privileges. The current warning will be replaced by an error before the release of Drupal 10.0.0."

I ahve also updated the title and the summary to only talk about creating the extension.

mondrake’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/system.install
@@ -460,6 +460,28 @@ function system_requirements($phase) {
+      'title' => t('The pg_trgm extension'),

I'd rather say t('PostgreSQL pg_trgm database extension')

+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -1060,6 +1060,40 @@ protected function hashBase64($data) {
+  /**
+   * Determines whether the PostgreSQL extension is created.
+   *
+   * @param string $name
+   *   The name of the extension.
+   *
+   * @return bool
+   *   Return TRUE when the extension is created, FALSE otherwise.
+   *
+   * @internal
+   */
+  public function extensionExists($name): bool {
+    return (bool) $this->connection->query('SELECT installed_version FROM pg_available_extensions WHERE name = :name', [
+      ':name' => $name,
+    ])->fetchField();
+  }
+
+  /**
+   * Determines whether the PostgreSQL extension is available.
+   *
+   * @param string $name
+   *   The name of the extension.
+   *
+   * @return bool
+   *   Return TRUE when the extension is available, FALSE otherwise.
+   *
+   * @internal
+   */
+  public function extensionAvailable($name): bool {
+    return (bool) $this->connection->query('SELECT name FROM pg_available_extensions WHERE name = :name', [
+      ':name' => $name,
+    ])->fetchField();

two methods here seem a bit overkill, I think it'd be better have one select and return an array of [name, installed_version], then do the processing in calling code.

andypost’s picture

There's new major release is out so would be great to check support for the extension in 14.0

daffie’s picture

Updated the title as requested by @mondrake.
Changed back to the more simple solution from the patch of comment #10.

mondrake’s picture

Seems sensible to me, we warn the user something is wrong, point to the solution, but not fall in trying to provide all steps to solve, which would be overdoing IMO. +1 for RTBC, but needs someone to confirm the message works by testing manually.

daffie’s picture

Issue summary: View changes

Updating the IS with a bit more info about how to manual test this patch.

xurizaemon’s picture

Status: Needs review » Needs work
FileSize
35.12 KB
94.35 KB

Patch looks good and works, identifying that the pg_trgm is not enabled. I feel the wording could be simplified and clarified to direct the user to why pg_trgm is recommended (and will be required).

Current wording for the warning description is:

The pg_trgm extension is not created. This extension is only needed on a PostgreSQL database. Extensions on PostgreSQL can only be created by a database user with superuser privileges. The current warning will be replaced by an error before the release of Drupal 10.0.0.

I propose:

The pg_trgm PostgreSQL extension is not present, which may impact Drupal's performance when using PostgreSQL DB. pg_trgm will be required by Drupal 10. See Drupal database server requirements for more information.

Reasoning behind this rewriting:

  • Tell the user why pg_trgm is important enough to recommend/require: performance.
  • Simplify the version string from 10.0.0 to 10 - the two extra zeroes don't add anything (maths joke?)
  • Don't try to document PostgreSQL details here; link to Drupal's official docs instead; that page is the correct place to point people to PostgreSQL guidance on creating extensions.
  • Two links to "create" felt repetitive, and the first one I felt like the word "not" should be part of the link?

The linked DB docs don't currently include the linkage to creating extensions under PostgreSQL, but I feel that's the right place to move those links to.

Testing

I created a fresh Drupal 9.3.x environment with the patch from #18 and a PostgreSQL DB (10.12) on Lando.

~/Projects/drupal-core/.lando.yml:

name: drupal-core
recipe: drupal9
env:
  DRUSH_OPTIONS_URI: http://drupal-core.lndo.site
config:
  database: postgres
  webroot: .

I also required drush/drush.

I installed Drupal on PostgreSQL.

lando drush site-install standard --db-url=pgsql://postgres@database/drupal9

I checked the requirements warning in CLI, where it appears correctly. (screenshot of CLI output, abbreviated below)

$ lando drush core:requirements
+------------------------------+----------+---------------+
| Title                        | Severity | Summary       |
+------------------------------+----------+---------------+
| Database system              | Info     | PostgreSQL    |
|                              |          |               |
| Database system version      | Info     | 10.12         |
|                              |          |               |
| Drupal                       | Info     | 9.3.0-dev     |
|                              |          |               |
| PostgreSQL pg_trgm extension | Warning  | Not created   |
+------------------------------+----------+---------------+

I checked the web UI for the warning also (screenshot of warning in browser). NB: I've removed an unrelated Drupal warning from this image for clarity.

I created the extension:

$ lando drush sqlc
drupal9=# create extension pg_trgm;

The warning was no longer displayed once the extension was created. I then dropped the extension, and saw that the warning was once more visible.

The functionality is great, setting NW for proposed wording changes. Thanks everyone!

xurizaemon’s picture

xurizaemon’s picture

Tested with PostgreSQL 13 also, success also.

My recollection from #2988018: [PP-1] Performance issues with path alias generated queries on PostgreSQL was that there was index configuration / regeneration required after the pg_trgm extension was enabled. Is the scope of this issue solely to ensure that required extension is available to the DB engine?

daffie’s picture

Status: Needs work » Needs review
FileSize
1.37 KB
2.21 KB

@xurizaemon: Thank you for your review.

Is the scope of this issue solely to ensure that required extension is available to the DB engine?

Yes, that is correct and if the extension is not installed, then we give a hook_requirements warning. We will not be using the extension in D9. We are preparing site owners for the fact that in D10 the extension will be required. For D10 we shall change the warning to an error. An error will block installing or upgrading to D10.

I propose:

The pg_trgm PostgreSQL extension is not present. We will be using the extension to improve Drupal's performance when using PostgreSQL in Drupal 10. The extension be required by Drupal 10. See Drupal database server requirements for more information.

I have changed your proposal a bit to make it clear that we will not be using it in D9.

For the 2 extra zero's in 10.0.0 reference minor and patch version numbers. See: https://semver.org/.

jweowu’s picture

We will not be using the extension in D9

Is there any reason why, IFF the extension is detected as enabled, that an option to create the path_alias indexes wouldn't be provided for Drupal 9 ?

If the requirements test for "is the pg_trm extension enabled?" succeeds, then the additional test "are the pg_trm indexes present on the path_alias table?" could be executed, with a warning and a link to generate them if the answer is "no".

daffie’s picture

Is there any reason why, IFF the extension is detected as enabled, that an option to create the path_alias indexes wouldn't be provided for Drupal 9 ?

Yes, we can do that. Only it will be a lot more work. We shall then have to support sites on PostgreSQL with the extension installed and sites without. Then we have to also support sites that change from without the extension to with the extension and the other way around. That is a lot of work in code as a lot of work in communication. As I am getting not much help with this problem, it was my decision to do it in the way that is the least amount of work (a.k.a. only start using it in D10).

If we do not get this issue to land in D9.3, there is a good change that using pg_trgm extension will be postponed to D11.

jweowu’s picture

Understood. My suggestions could be follow-ups in any case -- there's no reason why they should delay the current issue.

mondrake’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs manual testing

Just a nit on language:

+++ b/core/modules/system/system.install
@@ -472,6 +472,19 @@ function system_requirements($phase) {
+      'description' => t('The <a href=":pg_trgm">pg_trgm</a> PostgreSQL extension is not present. We will be using the extension to improve Drupal\'s performance when using PostgreSQL in Drupal 10. The extension be required by Drupal 10. See <a href=":requirements">Drupal database server requirements</a> for more information.', [
We will be using the extension to improve Drupal\'s performance when using PostgreSQL in Drupal 10. The extension be required by Drupal 10.

seems duplicate, I suggest

The extension will be required by Drupal 10 to improve Drupal performance when using PostgreSQL.

Manually tested in #21.

daffie’s picture

Updated the patch with the suggestion from comment #28.

@mondrake: Thank you for the review and the RTBC!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests
+++ b/core/modules/system/system.install
@@ -472,6 +472,19 @@ function system_requirements($phase) {
+  // Test with PostgreSQL databases for the status of the pg_trgm extension.
+  if (Database::isActiveConnection() && (Database::getConnection()->driver() == 'pgsql') && !Database::getConnection()->schema()->extensionExists('pg_trgm')) {
+    $requirements['pgsql_extension_pg_trgm'] = [
+      'severity' => REQUIREMENT_WARNING,
+      'title' => t('PostgreSQL pg_trgm extension'),
+      'value' => t('Not created'),
+      'description' => t('The <a href=":pg_trgm">pg_trgm</a> PostgreSQL extension is not present. The extension will be required by Drupal 10 to improve Drupal performance when using PostgreSQL. See <a href=":requirements">Drupal database server requirements</a> for more information.', [
+        ':pg_trgm' => 'https://www.postgresql.org/docs/current/pgtrgm.html',
+        ':requirements' => 'https://www.drupal.org/docs/system-requirements/database-server-requirements',
+      ]),
+    ];
+  }
+

This can have tests on postgres ie. we can test for an extension we know to exist and one we are sure does not and test the return values.

Also I think this warning should only occur on new installs and at runtime. I.e. I don't think we should issue this warning on an update at the moment because if someone is doing a security update I don't think that they need to be thinking about this warning.

Creditting @Mixologic as per issue summary.

alexpott’s picture

Reading the postgres docs are we sure about the whole super user requirement thing?

The docs say:

This module is considered “trusted”, that is, it can be installed by non-superusers who have CREATE privilege on the current database.

alexpott’s picture

The docs changed for postrges 13 and 14 to add that line. I'm pretty sure for postgres 13 and 14 we can install the extension automatically so I think this change should account for that.

daffie’s picture

The docs changed for postrges 13 and 14 to add that line. I'm pretty sure for postgres 13 and 14 we can install the extension automatically so I think this change should account for that.

That sounds great, only this is for D9 and the minimum required version is PostgreSQL 10. For D10 the minimum required version of will be PostgreSQL 12. Unless we are changing the minimum required version for PostgreSQL for Drupal 10, this is something that will need to wait for Drupal 11.

From the PostgreSQL 13 release notes; "Such extensions can be installed in a database by users with database-level CREATE privileges, even if they are not superusers." See: https://www.postgresql.org/docs/13/release-13.html.

As for adding tests for this change: At the moment we do not have any PostgreSQL 13 or higher testbots. We have #3240346: Add Postgresql 15.4/16.0 to CI. My question is do we want to wait for that or not. This issue need to land in D9.3 to give site owners a warning about the requirement!

@todo: "Also I think this warning should only occur on new installs and at runtime. I.e. I don't think we should issue this warning on an update at the moment because if someone is doing a security update I don't think that they need to be thinking about this warning."

longwave’s picture

+++ b/core/modules/system/system.install
@@ -472,6 +472,19 @@ function system_requirements($phase) {
+      'description' => t('The <a href=":pg_trgm">pg_trgm</a> PostgreSQL extension is not present. The extension will be required by Drupal 10 to improve Drupal performance when using PostgreSQL. See <a href=":requirements">Drupal database server requirements</a> for more information.', [

A tiny nit but there are 3 "Drupal"s in this paragraph, I think we can change the middle sentence to just say "The extension will be required by Drupal 10 to improve performance when using PostgreSQL."

alexpott’s picture

@daffie re tests...

+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -1060,6 +1060,23 @@ protected function hashBase64($data) {
+  public function extensionExists($name): bool {
+    return (bool) $this->connection->query('SELECT installed_version FROM pg_available_extensions WHERE name = :name', [
+      ':name' => $name,
+    ])->fetchField();
+  }

This must be testable on the CI supported version of PostgreSQL.

daffie’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
2.48 KB
3.5 KB

I have updated the warning message as requested by @longwave in comment #35.

This must be testable on the CI supported version of PostgreSQL.

On the current CI this is only possible, because the PostgreSQL database user in the testbot has superuser privileges. To me that is wrong and we should not add tests that use those privileges.
As of PostgreSQL 13 the required privileges to execute the added test will be lowered to users with create privileges. A normal database user for Drupal should have those privileges. Therefor adding the new test is OK.

daffie’s picture

Removed a couple of spaces.

daffie’s picture

alexpott’s picture

+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -1060,6 +1060,23 @@ protected function hashBase64($data) {
+    return (bool) $this->connection->query('SELECT installed_version FROM pg_available_extensions WHERE name = :name', [

+++ b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
@@ -1347,4 +1347,28 @@ public function testDefaultAfterAlter() {
+    // Make sure that the extension is created.
+    $this->connection->query('CREATE EXTENSION IF NOT EXISTS "pg_trgm"');
+    $this->assertTrue($this->schema->extensionExists('pg_trgm'));
+
+    // Drop the extension.
+    $this->connection->query('DROP EXTENSION "pg_trgm"');
+    $this->assertFalse($this->schema->extensionExists('pg_trgm'));
+
+    // Make sure that the extension is created as other tests may rely on the
+    // extension.
+    $this->connection->query('CREATE EXTENSION IF NOT EXISTS "pg_trgm"');

pg_trgm is installed on DrupalCI right? So we only need to test that it is installed. Going by my local psql you could probably test that plpgsql is installed.

Imo this test shouldn't be installing an extensions but it is perfectly acceptable to assume that an extension is installed.

alexpott’s picture

+++ b/core/modules/system/system.install
@@ -472,6 +472,19 @@ function system_requirements($phase) {
+  // Test with PostgreSQL databases for the status of the pg_trgm extension.
+  if (Database::isActiveConnection() && (Database::getConnection()->driver() == 'pgsql') && !Database::getConnection()->schema()->extensionExists('pg_trgm')) {
+    $requirements['pgsql_extension_pg_trgm'] = [
+      'severity' => REQUIREMENT_WARNING,
+      'title' => t('PostgreSQL pg_trgm extension'),
+      'value' => t('Not created'),
+      'description' => t('The <a href=":pg_trgm">pg_trgm</a> PostgreSQL extension is not present. The extension will be required by Drupal 10 to improve performance when using PostgreSQL. See <a href=":requirements">Drupal database server requirements</a> for more information.', [
+        ':pg_trgm' => 'https://www.postgresql.org/docs/current/pgtrgm.html',
+        ':requirements' => 'https://www.drupal.org/docs/system-requirements/database-server-requirements',
+      ]),
+    ];
+  }

So the prefix deprecation is also being checked on update. I think this is wrong. We should only be making deprecation checks at runtime. They shouldn't interrupt an install or an update at this point. So I think this should be in a if ($phase === 'runtime') { and we should open an issue to make the prefix deprecation only occur at runtime.

catch’s picture

Status: Needs review » Needs work

Agreed with #42 - this should be a runtime warning in Drupal 9, and an upgrade error for Drupal 10.

daffie’s picture

Changed the test and made it an runtime only warning.

mondrake’s picture

Status: Needs review » Needs work
+++ b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
@@ -1347,4 +1347,20 @@ public function testDefaultAfterAlter() {
+    $this->connection->query('CREATE EXTENSION IF NOT EXISTS "pg_trgm"');

I do not think we should be doing this. The effect of this would go beyond the scope of the test if the extension was not created previously. Per #40, let's just test the extension is there. In DrupalCI is OK, and running the tests locally from Drupal 9.3 onwards will simply point the testers to create the extension in their environment.

daffie’s picture

@mondrake: Thank you for the review.

For #44: Fixed.

mondrake’s picture

Status: Needs review » Reviewed & tested by the community

AFAICS, all feedback addressed. Back to RTBC.

  • catch committed 84e8b97 on 9.4.x
    Issue #3214921 by daffie, xurizaemon, alexpott, mondrake, andypost,...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed 84e8b97 and pushed to 9.4.x. Thanks! Also cherry-picked to 9.3.x.

  • catch committed 0c936b4 on 9.3.x
    Issue #3214921 by daffie, xurizaemon, alexpott, mondrake, andypost,...
mondrake’s picture

Status: Reviewed & tested by the community » Fixed

? Status change did not work :(

catch’s picture

Issue summary: View changes
Issue tags: +9.3.0 release notes
Gábor Hojtsy’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

djassie’s picture

For using Lando, it will resolve issues with Drupal 10 and postgreSQL


lando psql

\c drupal10

create extension pg_trgm;