Problem/Motivation

Per our Schema API documentation, each column of a unique key of a table schema can be specified either as a column name or as an array of column name and length:

* - 'unique keys': An associative array of unique keys ('keyname' =>
* specification). Each specification is an array of one or more
* key column specifiers (see below) that form a unique key on the table.

* A key column specifier is either a string naming a column or an
* array of two elements, column name and length, specifying a prefix
* of the named column.

The PostreSQL database backend does not support the latter case. The relevant code is in lines 135 to 139 of \Drupal\Core\Database\Driver\pqsql\Schema::createTableSql():

    if (isset($table['unique keys']) && is_array($table['unique keys'])) {
      foreach ($table['unique keys'] as $key_name => $key) {
        $sql_keys[] = 'CONSTRAINT ' . $this->prefixNonTable($name, $key_name, 'key') . ' UNIQUE (' . implode(', ', $key) . ')';
      }
    }

The $key variable in the foreach can be (per the API documentation) for example array(array('foo', 123)) in which case the implode() fails. The resulting string will then be Array and the resulting SQL will fail hard.

Proposed resolution

Remaining tasks

User interface changes

API changes

Comments

tstoeckler’s picture

berdir’s picture

Well, a unique key constraint on a partial column is IMHO useless because it would then fail on longer, non-identical strings that are the same for the first N characters? That makes no sense :) Same for a primary key.

Instead of trying to fix this, which PostgreSQL might not even support, we should fix the fact that we are generating a partial unique key constraint and instead limit the column size of file.uri?

bzrudi71’s picture

Title: The PostreSQL database driver does not support unique keys specified as an array of column name and length » The PostreSQL database driver does not support unique keys specified as an array of column name and length (breaks PG installation)

Should be mentioned that this breaks PostgreSQL installation...

ERROR:  syntax error at or near "Array" at character 484
STATEMENT:  CREATE TABLE file_managed (
		fid serial CHECK (fid >= 0),
		uuid varchar(128) NOT NULL,
		langcode varchar(12) NOT NULL,
		uid bigint CHECK (uid >= 0) NOT NULL,
		filename varchar(255) NULL,
		uri varchar(2048) NOT NULL,
		filemime varchar(255) NULL,
		filesize bigint CHECK (filesize >= 0) NULL,
		status smallint NOT NULL,
		created int NULL,
		changed int NOT NULL,
		PRIMARY KEY ("fid"),
		CONSTRAINT file_managed_file__uuid_key UNIQUE (uuid),
		CONSTRAINT file_managed_file__uri_key UNIQUE (Array)
	)
tstoeckler’s picture

So I found this gem in the MySQL documentation:

If you specify a prefix value for a column in a UNIQUE index, the column values must be unique within the prefix.

I searched for something similar in PostreSQL and couldn't find anything, but for some notes of "exclusion constraints", but I didn't really grok what those were. It might be that they're completely unrelated - it might be that you're able to achieve a similar behavior with them in PostgreSQL. It doesn't seem like that would be trivial to implement, though.

I have no idea whatsoever if this is ANSI SQL (or if the ANSI standard is even relevant to unique keys).

In any case: This is incredibly strange behavior and is something I do not think we want to support. If I want a field to be unique, I want it to be unique, not only the first part. If - for whichever reason - I do want this behavior I personally think it's fine to have the validation only in PHP (where I need to have it anyway) and not be able to reap the benefit of a faster SQL query by using a unique key prefix which may or may not be supported by all backends anyway.

So to my mind, we should remove that part of the API wholesale, as I think it is confusing and pointless to begin with. Leaving the title for now, though, as to get more consensus on that.

To solve the actual problem with the PostgreSQL installation I opened: #2279363: file_managed.uri should not specify a prefixed unique key

damien tournoud’s picture

PostgreSQL can do this with functional indexes:

CREATE UNIQUE INDEX idx_name ON table_name (substr(col, 0, N)); 

But those type of unique constraints usually don't make that much sense.

tstoeckler’s picture

Title: The PostreSQL database driver does not support unique keys specified as an array of column name and length (breaks PG installation) » Drop support for unique keys specified as an array of column name and length (breaks PG installation)

OK, being bold here. Although @Berdir, @Damien Tournoud, and @sun (in #2279363-2: file_managed.uri should not specify a prefixed unique key) - albeit tentatively - agreeing on this doesn't even seem that bold.

Let's just kill this very pointless "feature".

Re-titling, re-classifying as 'task', and postponing on #2279363: file_managed.uri should not specify a prefixed unique key: We can only remove support once we remove usages.

Other than that the following should be enough for this issue:

  • Remove this mention of this from the hook_schema() documentation
  • Simplify/remove code that currently supports this: the PostgreSQL backend should need no change, not sure about SQLite
  • Write a change notice
tstoeckler’s picture

Category: Bug report » Task
Status: Active » Postponed
stefan.r’s picture

Issue tags: +PostgreSQL
tstoeckler’s picture

Component: postgresql db driver » database system
Status: Postponed » Active
andypost’s picture

suppose it makes sense to use functional indexes to prevent subject

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

rosk0’s picture

Version: 8.4.x-dev » 8.5.x-dev
Component: database system » postgresql db driver
Parent issue: #2157455: [Meta] Make Drupal 8 work with PostgreSQL or remove support from core before release » #2564307: [meta] Remaining Drupal 10/11 PostgreSQL issues

Just installed fresh copy of 8.5.x in PostgreSQL without any issues. Enabled all the core modules including the ones from "Web services" section - no issues.

Should we cancel this one?

Moving to other parent just in case.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mondrake’s picture

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.