Problem/Motivation
Views can generate SQL alias names in excess of the intended 60 character limit. This can happen particularly when dealing with relationship joins. A too-long value which is not truncated can fail on databases with identifier limits (e.g. 63 characters for Postgres identifiers). A too-long value which is naively truncated can easily conflict with other similarly-truncated aliases based on the same relationships.
Steps to reproduce
Create a View similar to the one described under Original report below.
TODO: A step-by-step example would be useful.
Proposed resolution
When a generated alias exceeds 60 characters, introduce a short hash of that original alias into the name (within the first 60 characters), and truncate the result to 60 characters.
Remaining tasks
* Improve steps to reproduce
* Patch review
User interface changes
N/A
API changes
Added: Drupal\views\Plugin\views\query\Sql::sanitizeAlias()
Data model changes
N/A
Release notes snippet
Views SQL aliases which exceed 60 characters are truncated and uniquified based on a hash of the original name.
Original report
We are running our Drupal on PostgreSQL and we have a view with 2 relations (join tables). The Preview SQL is attached below.
Due to the table names and field names, Views generates a field alias longer than 63 characters, node_node_data_field_parent_node_node_data_field_pbcontent_year_field_pbcontent_year_value, causing PostgreSQL not to throw an error, but truncate the name in the resultset. PostgreSQL will only return node_node_data_field_parent_node_node_data_field_pbcontent_year as the column name in the resultset, which causes Views to break, as there is no data in the expected field node_node_data_field_parent_node_node_data_field_pbcontent_year_field_pbcontent_year_value.
SELECT node_node_data_field_parent_node_node_data_field_pbcontent_year.field_pbcontent_year_value AS node_node_data_field_parent_node_node_data_field_pbcontent_year_field_pbcontent_year_value,
COUNT(DISTINCT(node.nid)) AS num_records
FROM node node
LEFT JOIN content_type_video node_data_field_video_gallery ON node.vid = node_data_field_video_gallery.vid
INNER JOIN node node_node_data_field_video_gallery ON node_data_field_video_gallery.field_video_gallery_nid = node_node_data_field_video_gallery.nid
LEFT JOIN content_type_video_gallery node_node_data_field_video_gallery_node_data_field_parent_node ON node_node_data_field_video_gallery.vid = node_node_data_field_video_gallery_node_data_field_parent_node.vid
INNER JOIN node node_node_data_field_parent_node ON node_node_data_field_video_gallery_node_data_field_parent_node.field_parent_node_nid = node_node_data_field_parent_node.nid
LEFT JOIN content_type_pbcontent node_node_data_field_parent_node_node_data_field_pbcontent_year ON node_node_data_field_parent_node.vid = node_node_data_field_parent_node_node_data_field_pbcontent_year.vid
WHERE (node.status <> 0) AND (node.type in ('video'))
GROUP BY node_node_data_field_parent_node_node_data_field_pbcontent_year_field_pbcontent_year_value
ORDER BY node_node_data_field_parent_node_node_data_field_pbcontent_year_field_pbcontent_year_value DESC
Could anyone provide me with a workaround? Renaming the base fields and thus getting an shorter alias for the column name would work, but is not an option at the moment.
I tried to rewrite the SQL with hook_views_query_alter(), replacing all aliases in $query->fields with an generic one, if the alias is longer than 63 chars. The query then runs fine, but Views2 continues to search for the long columnames in the resultset. Any way I can tell Views2 that it shouldn't expect the data in field "node_node_data_field_parent_node_node_data_field_pbcontent_year_field_pbcontent_year_value" but for example in "generic_1"?