Problem/Motivation

As part of the issue #2342045: Standard views base fields need to use same rendering as Field UI fields, for formatting, access checking, and translation consistency we realized that the logic in DefaultTableMapping::getFieldColumName()
does not work for fields stored on base tables ...

Proposed resolution

Make the method behave exactly how the storage structure behaves.

Note: https://www.drupal.org/files/issues/views-formatters-base-fields-2342045... already contains some kind of fix
and test coverage.

Remaining tasks

User interface changes

API changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

plach’s picture

Status: Active » Needs review
Issue tags: +Entity Field API, +sprint
FileSize
5.33 KB

Let's try this.

plach’s picture

plach’s picture

Issue tags: +Ghent DA sprint
dawehner’s picture

That was quick!

  1. +++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
    @@ -130,18 +130,33 @@ public function getFieldNames($table_name) {
    +    }
    +
    +    return $column_name;
    

    Let's throw the exception

  2. +++ b/core/tests/Drupal/Tests/Core/Entity/Sql/DefaultTableMappingTest.php
    @@ -235,6 +235,36 @@ public function testGetExtraColumns() {
    +
    +    return $data;
    

    So we need to expand the test coverage later as well ...

plach’s picture

plach’s picture

Correct interdiff

plach’s picture

Documented and cleaned-up things a bit

dawehner’s picture

  1. +++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
    @@ -130,18 +130,38 @@ public function getFieldNames($table_name) {
    +      throw new SqlContentEntityStorageException('Column information not available for the specified field.');
    

    It would be great to tell people which field actually caused the exception ...

  2. +++ b/core/tests/Drupal/Tests/Core/Entity/Sql/DefaultTableMappingTest.php
    @@ -235,6 +236,76 @@ public function testGetExtraColumns() {
    +    try {
    +      $result = $table_mapping->getFieldColumnName($definitions[$field_name], $column);
    +      $this->assertEquals($expected, $result);
    +    }
    +    catch (SqlContentEntityStorageException $e) {
    +      $this->assertTrue($exception);
    +    }
    

    You could have also just made an extra test method with an @expectedException but sure, this is up to you to decide.

dawehner’s picture

Status: Needs review » Needs work

Let's quickly mark it as needs work.

yched’s picture

  1. +++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
    @@ -130,18 +130,38 @@ public function getFieldNames($table_name) {
    +      $this->columnMapping[$field_name] = array();
    +      foreach (array_keys($this->fieldStorageDefinitions[$field_name]->getColumns()) as $column_name) {
    +        $this->columnMapping[$field_name][$column_name] = $this->getFieldColumnName($this->fieldStorageDefinitions[$field_name], $column_name);
    +      }
    +    }
    +    return $this->columnMapping[$field_name];
    

    Lovely :-)
    For readability, I guess we could extract
    $storage_definition = $this->fieldStorageDefinitions[$field_name]; ?

  2. +++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
    @@ -130,18 +130,38 @@ public function getFieldNames($table_name) {
    +  public function getFieldColumnName(FieldStorageDefinitionInterface $storage_definition, $column_name) {
    

    So we're not :
    - moving to "only use the column name without prefixing with the field name in dedicated tables",
    - nor fixing the inconsistency of single or double underscore separator
    in that issue ?

dawehner’s picture

moving to "only use the column name without prefixing with the field name in dedicated tables",
- nor fixing the inconsistency of single or double underscore separator
in that issue ?

I would strongly disagree with changing this here, because the amount of work needed to also fix that, is quite a lot,
and it would be nice to be able to work on the big views critical at the same time.

On top of that, it would for example require quite some discussion whether its really fine to rename table columns at that point.

tstoeckler’s picture

Very nice fix. I briefly discussed this with @dawehner in IRC a while back but I did not come up with this solution. Great!

One thing though:

+++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
@@ -130,18 +130,38 @@ public function getFieldNames($table_name) {
+  public function getFieldColumnName(FieldStorageDefinitionInterface $storage_definition, $column_name) {
...
+    return $column_name;

I thinl double usage of variables is not only rather confusing but is also very error-prone if we ever decide to touch this in the future. Let's rename either of the $column_name variables please.

yched’s picture

@tstoeckler - double usage of $column_name variable : very true.

Actually, it's a problem that the var names and method names use "column name" for both:
- the raw property name in the field schema ('value')
- the actual, final column name in the schema ('field_name__value')

Since getFieldColumnName() is in TableMappingInterface, maybe keep "column name" for the actual schema column, and "property" for the raw property name ?

plach’s picture

Status: Needs work » Needs review
FileSize
7.84 KB
9.42 KB

Good points, thanks!

dawehner’s picture

  1. +++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
    @@ -130,18 +131,40 @@ public function getFieldNames($table_name) {
    +  public function getFieldColumnName(FieldStorageDefinitionInterface $storage_definition, $property_name) {
    
    @@ -319,11 +342,4 @@ protected function generateFieldTableName(FieldStorageDefinitionInterface $stora
    -  public function getFieldColumnName(FieldStorageDefinitionInterface $storage_definition, $column) {
    

    Now that we renamed the variable name on the method, we should really update the interface as well. technically we don't have to, but it would be just lazy, to not do it.

  2. +++ b/core/tests/Drupal/Tests/Core/Entity/Sql/DefaultTableMappingTest.php
    @@ -235,6 +236,87 @@ public function testGetExtraColumns() {
    +   * @expectedException \Drupal\Core\Entity\Sql\SqlContentEntityStorageException
    +   * @expectedExceptionMessage Column information not available for the "test" field.
    +   *
    

    Thank you!

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

I'm stupid, blind.

yched’s picture

Status: Reviewed & tested by the community » Needs work

Sorry :-/

  1. +++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
    @@ -130,18 +131,40 @@ public function getFieldNames($table_name) {
    +      foreach (array_keys($this->fieldStorageDefinitions[$field_name]->getColumns()) as $column_name) {
    

    foreach (aray_keys($field_storage_definition)->getColumns() as $property_name)) {

    I know the FSDI method is getColumns() :-/, but IMO we should name our vars according to the business logic this code here is about, which is : "compute schema column names for a field property".

    We want to avoid
    $mapping[$column_name] = get the column name for column name :-p

  2. +++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
    @@ -130,18 +131,40 @@ public function getFieldNames($table_name) {
            foreach (array_keys($this->fieldStorageDefinitions[$field_name]->getColumns()) as $column_name) {
    +        $storage_definition = $this->fieldStorageDefinitions[$field_name];
    

    I meant $storage_definition should be defined one line up and used in the foreach() line as well :-p

  3. +++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
    @@ -130,18 +131,40 @@ public function getFieldNames($table_name) {
    +  public function getFieldColumnName(FieldStorageDefinitionInterface $storage_definition, $property_name) {
    +    $column_name = $property_name;
    

    Why do we start with $column_name = $property_name ?
    There's currently no case where the final column name in the schema is equal to the property name, right ?

  4. +++ b/core/lib/Drupal/Core/Entity/Sql/TableMappingInterface.php
    @@ -94,12 +94,12 @@ public function getReservedColumns();
    -   * @param string $column
    +   * @param string $property_name
        *   The name of the column.
    

    The param description text should be updated accordingly ? :-)

plach’s picture

Why do we start with $column_name = $property_name ?
There's currently no case where the final column name in the schema is equal to the property name, right ?

Actually there is one case, I refactored the related code a bit to make it more clear.

plach’s picture

Status: Needs work » Needs review
plach’s picture

Status: Needs review » Needs work

The last submitted patch, 20: entity-base_fields_column_name-2392209-20.patch, failed testing.

The last submitted patch, 18: entity-base_fields_column_name-2392209-18.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
FileSize
1.64 KB
9.5 KB

Forgot to update unit tests :(

Attaching interdiff #18

swentel’s picture

+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageException.php
@@ -0,0 +1,16 @@
+ * Exception thrown when a SQL storage operation fail.

Extreme nitpick: fail should fails ?

yched’s picture

@plach: yay, thanks !

Once @swentel's #24 is fixed, this is RTBC if green.

plach’s picture

yched’s picture

Status: Needs review » Reviewed & tested by the community

Thanks !

The bot will tell us when he is kind enough to grab this :-)

The last submitted patch, 23: entity-base_fields_column_name-2392209-21.patch, failed testing.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 26: entity-base_fields_column_name-2392209-26.patch, failed testing.

Status: Needs work » Needs review
swentel’s picture

Status: Needs review » Reviewed & tested by the community

Looks like a bot fluke

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 26: entity-base_fields_column_name-2392209-26.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
FileSize
1.64 KB
9.57 KB

I had to revert the changes introduced in #21: it broke entity query conditions on the deleted field property.

yched’s picture

Status: Needs review » Reviewed & tested by the community

OK, never mind then, we'll keep the cleanup of reservedColumns() for another issue. Sorry about that.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

This issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes. Committed bcfde9e and pushed to 8.0.x. Thanks!

  • alexpott committed bcfde9e on 8.0.x
    Issue #2392209 by plach: DefaultTableMapping::getFieldColumName is...
yched’s picture

Status: Fixed » Closed (fixed)

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