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"?
Comment | File | Size | Author |
---|
Issue fork drupal-571548
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #1
0xAFFE CreditAttribution: 0xAFFE commentedI have this problem too and so have other users: http://drupal.org/node/371711
Comment #2
0xAFFE CreditAttribution: 0xAFFE commentedHere is a patch, please try.
Comment #3
k4ml CreditAttribution: k4ml commentedI test the patch in #2 and so far it works.
Comment #4
merlinofchaos CreditAttribution: merlinofchaos commentedOk, so the patch looks ok, but it does not conform to coding standards. For example, function arguments should have proper spacing, } should always be followed by a newline.
Comment #5
merlinofchaos CreditAttribution: merlinofchaos commentedAlso, in looking at this it seems like this really should happen during add_field(), not during query() -- because aliases get returned to the function for later use. That means changing them could change them out from under a handler. That seems odd to me.
Comment #6
0xAFFE CreditAttribution: 0xAFFE commentedI'll rewrite the patch that it uses add_field(), but where should I put the safe_alias counter? should I introduce a new member to the query object? This counter is needed, because when very long aliases (esp with cck and relations) have the some shortened prefix I need a counting number so I can distinguish between them.
Comment #7
merlinofchaos CreditAttribution: merlinofchaos commentedI think add_field already performs collision detection. Are you sure you still need to do that?
If you really do,then go ahead and stick the counter on $query, but I am dubious that it is necessary.
Comment #8
dagmarWe should fix this before alpha 2 of views 3.
I have created a patch for this in views 3 http://drupalbin.com/12557
I didn't post here because for views 2 doesn't apply.
Also I have remember Earl said something about fix this issue using views_safe_alias() from here #576694: Enable views to handle external tables properly, allowing for joins across tables in different mysql databases
Comment #9
dawehnerThis is a version for views3
Comment #10
dawehnerWhy not do this on add_field level?
It is returned the alias by default, so people can work with the new alias, if needed.
Comment #11
0xAFFE CreditAttribution: 0xAFFE commentedIf you have these two aliases:
They would both have the safe prefix of 'node_event_customers2event_node_data_field_account_zipcode_f' which of course will colide and I need to give them unique names like 'node_event_customers2event_node_data_field_account_zipcode_f_1' and 'node_event_customers2event_node_data_field_account_zipcode_f_2'.
I looked at add_field and could not see any collision detection?!?
Comment #12
0xAFFE CreditAttribution: 0xAFFE commentedReworked the patch. safe_aliases are now generated in add_field. The patch builds upon the old patch from #2
I used code-style.pl to check for compliance to the coding standards. One thing I was a bit unsure about:
code-style.pl complained about missing space in front of the {, but this looks a bit special to me.
Comment #13
dawehnercodestyle.pl is quite bad.
Please make a batch from the head version, not relative to your old patch
I'm on crack. Are you, too?
Comment #14
0xAFFE CreditAttribution: 0xAFFE commentedI have recreated the patch based on the latest devel snapshot.
Comment #15
dagmarLets move this issue to 6.x-3.x version and then back-port it.
Comment #16
dagmarI think this should be enough.
Comment #17
dawehnerMakes more sense.
Comment #18
merlinofchaos CreditAttribution: merlinofchaos commentedCan someone with pgsql confirm #16 fixes the problem they were having?
Comment #19
dagmarOk, I have tested with a very long field and get this error:
This occurs only when a very long alias is used in the ORDER BY
Comment #20
dagmarLets try this patch
Comment #21
merlinofchaos CreditAttribution: merlinofchaos commentedCommited to 3.x in both 7.x and 6.x -- just need to backport to 2.x and that should be trivial.
Comment #22
merlinofchaos CreditAttribution: merlinofchaos commentedUntag.
Comment #23
dawehnerHere it is
Comment #24
dawehnerUpdate
Comment #25
dawehnerremove todo
Comment #26
hawleyal CreditAttribution: hawleyal commentedPatch did not work Views 6.x-2.8.
No longer missing field values, but I still get duplicate alias errors.
Query:
Comment #27
JoelKleier CreditAttribution: JoelKleier commentedI tested the patch from #25 on views 6.x-2.8 w/ drupal 6.16 and I'm not seeing the errors from #26 anywhere -- I'm still somewhat new to drupal, so should I be looking somewhere besides the Recent log entries or on a page that would execute these queries?
Comment #28
dawehnerIf you think about dagmars approahc, it cannot work. We have to create different aliases.
Comment #29
Josh Waihi CreditAttribution: Josh Waihi commentedI've modified the patch to make the alias shorten from the end rather than the front. This makes the alias more likely to be unique.
Comment #30
Josh Waihi CreditAttribution: Josh Waihi commentedmaybe this issue is realated to #742006: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
Comment #31
dawehner@Josh Waihi
Mh i still think that this will work everytime there could be this example
maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaan_is_this_a_long_alias
maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaan_is_this_a_long_alias2
tmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaan_is_this_a_long_alias
So i guess we need to add a counter at the end to be 100%sure
Comment #32
Josh Waihi CreditAttribution: Josh Waihi commentedsure, though I'd like to point out your alias examples are extremely unlikely. CCK is generally the culprit of this bug and there naming schema is something like (though not excatly) [module]_[table]_[table_alias]_[column]_[column_alias] so the closer to the end the alias is, the more unique it becomes.
Also discard #30, that was for another issue sorry.
Comment #33
merlinofchaos CreditAttribution: merlinofchaos commentedPart of the reason I never fixed that @fixme in there was that I was afraid there would be some unintended consequence of doing so. That means if we fix that, we'll need to thoroughly test this patch. Are you sure we want to do that here?
Comment #34
BoobaaApplied the patch in #29 to views-6.x-2.9, without success: it yields different errors for different views.
user warning: query: SELECT DISTINCT FIRST(DISTINCT(node.nid)) AS nid, FIRST(node_node_data_field_local_authors.title) AS _local_authors_title, FIRST(node_node_data_field_local_authors.nid) AS ield_local_authors_nid, FIRST(node_node_data_field_local_authors.language) AS _authors_language, FIRST(node.type), FIRST(node_data_field_taxo_evszam.field_taxo_evszam_value) AS zam_value, FIRST(node_data_field_taxo_evszam.field_publicationtitle_value) AS alue, FIRST(node_data_field_taxo_evszam.field_publicationtitle_format) AS mat, FIRST(node_data_field_taxo_evszam.field_kotet_oldal_value) AS dal_value FROM mikrobi_node node LEFT JOIN mikrobi_content_field_local_authors node_data_field_local_authors ON node.vid = node_data_field_local_authors.vid INNER JOIN mikrobi_node node_node_data_field_local_authors ON node_data_field_local_authors.field_local_authors_nid = node_node_data_field_local_authors.nid LEFT JOIN mikrobi_content_type_publikacio node_data_field_taxo_evszam ON node.vid = node_data_field_taxo_evszam.vid WHERE (node.status <> 0) AND (node.type in ('publikacio')) AND (node.language in ('hu', '')) AND (node_node_data_field_local_authors.nid = 45) GROUP BY node.nid ORDER BY ASC in /var/www/foo/sites/all/modules/contrib/views/includes/view.inc on line 775.
Without the patch there are no displayed errors, but some of the fields are not displayed, since their views-generated field alias is too long. Anyway, being a PGSQL/Views newbie I don't even know how to continue.
Comment #35
Denes.Szabo CreditAttribution: Denes.Szabo commentedAccording to the pg documentation: http://www.postgresql.org/docs/8.1/interactive/runtime-config-preset.html, it seems the problem is the max_identifier_length parameter.
max_identifier_length (integer)
Reports the maximum identifier length. It is determined as one less than the value of NAMEDATALEN when building the server. The default value of NAMEDATALEN is 64; therefore the default max_identifier_length is 63.
This parameter is read-only. Cannot be altered after a db connection only if you recompile the whole postgresql.
In the pg 8.4 this value is 63 too, nothing changed. (pg from ubuntu repo).
Comment #36
BoobaaOK, this bug annoys me severely. The patch in #29 helped to solve a site running on PHP-5.2.14 & PGSQL-8.4.3, but gave the fatal errors mentioned in #34 with PHP-5.2.6-something-weird-that-debian-foolks-have-added-as-revision-number & PGSQL-8.3.11. Digging to the deeps of Views & CCK code, I had to come to the conclusion that the field aliases are simply left off in some cases. Digging even deeper into the problem (beyond my own elbows and my colleague's knees) I had to face that the bug was introduced by the patch in #29 - which has one serious flaw: the $alias will be empty if it's shorter than something, since PHP's substr() is... khm... a bit weird in some cases, especially with negative stuff.
So, here is my solution: do not try to shorten the aliases if they are not _too_ long.
The attached patch is a slightly modified version of the one in #29: it makes the aliases shorter only in the case they are too long (ie. longer than 60 chars). It does solve my problem on both the sites I have mentioned above, so be cautious with those stones.
Comment #37
Josh Waihi CreditAttribution: Josh Waihi commentedCan you explain what this is for?
Comment #38
Boobaa@Josh Waihi: it was taken from your patch in #29, so I thought you know what you are doing. ;) It was present in dereine's patch in #25, #24, #23, even in dagmar's one in #20, which is the point this was introduced in this issue. Anyway, I don't know what's that for exactly, to be honest.
Comment #39
dagmarHi, add_field function returns an alias. This is needed because you have to sort by alias and not by the original key.
I realized of this after #19.
Comment #40
valarauco CreditAttribution: valarauco commentedHi, I'm kinda new on Drupal and here me and my co-workers had the same problem. We applied the patch in #25 and it fixed the problem for a while but soon we had another issue because the patch makes "collision" aliases (I mean two or more aliases were the same). So we thought about how to make really unique alias, as a result we used MD5 (yes I know, it makes much less readable aliases but are unique...)
So I leave you our patch here(based in #25)
Comment #41
dagmarUse md5 is not the right solution, we have to find the raise of the problem for alias collision. (Maybe if you export your view it can help us)
Comment #42
mscalone CreditAttribution: mscalone commentedWhy is not the right solution? The SQL command is not meant to be interpreted by enybody .. or there is something I'm missing..
I had the same problem an the workaround was to create a theme for the field in the view with the following code:
I know this code doesn't work in the case where two fields have the same truncated prefix, but is not my case and the patch didn't work for me.
Comment #43
davidwhthomas CreditAttribution: davidwhthomas commented@valarauco #40
MD5 alias patch works fine for me and fixes the alias length issue, thanks.
I like the idea of an MD5 patch as it ensures the aliases are unique.
The SQL query can still be viewed and interpreted in the view edit preview panel.
cheers,
DT
Comment #44
DamienMcKennaGiven many tables are shortened by convention when writing manual queries, e.g. it's common place to alias "{node}" as just "n", why not use that within the identifier building to truncate "node_" to "n_", etc? A list of twenty or thirty common one & two-letter aliases could be agreed upon which should shorten some of this, e.g:
This would be beneficial for anyone using hook_views_query_alter(), not just people using PostgreSQL.
Comment #45
davidwhthomas CreditAttribution: davidwhthomas commented@#44 The problem there is an abbreviation may collide with other similarly named tables, e.g fields or content types with similar names.
A 32 character MD5 hash is guaranteed to be unique based on the table / field in question and requires no naming convention.
I'm using the patch from #40 and working well
DT
Comment #46
Boobaa@#45: Using the term „guaranteed” seems to be a bit harsh: have you _checked_ that _every_ identifier has _unique_ md5sum, with their possible length up to, eg., 128? ;) Instead „guaranteed to be unique” I would only say „likely to be unique with high probability”, or something -- in other words I would not simply and blindly take the assumption that this approach would work without glitches regarding to all the table names and other identifiers out there.
Comment #47
HnLn CreditAttribution: HnLn commentedFYI this impacts the calendar module: http://drupal.org/node/1038486
Comment #48
killes@www.drop.org CreditAttribution: killes@www.drop.org commentedThis is not only a postgres issue, I've had that happen in mysql too.
5.0.67-0.dotdeb.1-log
This happened for me with a "group by", generated by views_groupby
Comment #49
killes@www.drop.org CreditAttribution: killes@www.drop.org commentedHere's a patch that tries to address the problem.
The first part in ->execute could be put in the replacement hook before, but there's no such hook to clean up the results below.
Comment #50
madth3 CreditAttribution: madth3 commentedEven though I realize the MD5 solution is not ideal, patch from #40 solved the problem for me.
Thanks to @valarauco.
Comment #51
dawehner@madth3
Can you try the patch from killes, too?
Is there a reason why this issue for #49 is on "needs work"?
Comment #52
unwiredbrain CreditAttribution: unwiredbrain commentedStill having this problem on Views 6.x-2.12 using MySQL 5.1.41 64-bit.
Any news on this?
Comment #53
kevin.mcnamee@mailbox.org CreditAttribution: kevin.mcnamee@mailbox.org commentedThe patch committed in #21 is causing problems for Views Calc. See #1163514: Totals not displayed due to truncated variable names.
Comment #54
kevin.mcnamee@mailbox.org CreditAttribution: kevin.mcnamee@mailbox.org commentedChanging the version. The patch committed in #21 has the side-effect of introducing potential namespace collisions, for which several solutions have been suggested in the subsequent discussion on this thread. Therefore the issue still needs to be properly fixed in 6.3 before back-porting to 6.2.
/Kevin
Comment #55
marcp CreditAttribution: marcp commentedIt looks like there are 2 choices right now:
1. The MD5 fix in #40 which has been reported to work, but for which there is some concern that we could still have alias collisions;
2. The most recent patch in #49 which killes@www.drop.org submitted but did not set to "needs review" I think because he's concerned that "there's no such hook to clean up the results below"
If creating the unique alias in
add_field()
as merlinofchaos suggests way back in #7 is the way to go, it seems like we should be able to come to agreement on how to get this fixed.Can we:
1. Keep the long alias if it's less than 60 characters?
2. Use some simple means of generating an alias if it's >= 60 characters?
merlinofchaos has not chimed in on this since April 2010. If anyone has either tested the patch in #49 and gotten it to work or can supply another patch that would fix this in 6.x-3.x it would be great to get this to "needs review" again soon.
Comment #56
kevin.mcnamee@mailbox.org CreditAttribution: kevin.mcnamee@mailbox.org commented1) Yes. Could be handy if someone wants to debug or just examine their View. It also gives people to option to switch to short aliases for this purpose.
2) Some sort of hash with collision avoidance must be the way to go. If that rules out MD5, then there are others such as SHA1 that would do the job. Is performance an issue? See http://www.php.net/manual/en/function.hash.php#89574 for some figures.
/Kevin
Comment #57
marcp CreditAttribution: marcp commentedI don't get why we need to use a hash. Wouldn't a static counter work just as well? view_alias_1, view_alias_2, ...
Comment #58
kevin.mcnamee@mailbox.org CreditAttribution: kevin.mcnamee@mailbox.org commentedOK, I reread some of the early posts and it seems that a counter is a perfectly valid solution. The question is, which patch should we be testing?
Comment #59
marcp CreditAttribution: marcp commented@kmcnamee - I haven't tried any of them. The patch in #49 looks like it's doing something with a counter. It also looks like it's doing a lot more than the patch in #40.
Comment #60
kevin.mcnamee@mailbox.org CreditAttribution: kevin.mcnamee@mailbox.org commentedThe patch in #40 is the MD5 patch which we will skip for now. The patch in #49 does some clever things but not using MD5 (contrary yo the name of the patch). This patch could be our test candidate. Now, what exactly needs to be tested?I am hoping some of the original authors could chime in on this.
Comment #61
dawehnerCan you explain why this needs to be sorted?
Comment #62
Gribnif CreditAttribution: Gribnif commentedI'm kind of late coming to this topic, only just having upgraded to Views 6.x-3.0-alpha4. But I've got to ask one question:
Has anyone considered how much existing code is going to break due to this change when people upgrade? I'm right now having to go through 5 or 6 custom modules and 20 or 30 .tpl files in order to truncate the identifiers that have been shortened by this change. They worked fine in 6.x-2.x with MySQL, because its limit seems to be 256 characters. But due to the new truncation I'm now having to do a lot of extra work. And the truncated field names are nowhere near as human-readable.
Couldn't the truncation limit have been chosen based on the database engine being used? It would be a pretty simple matter to add a DB API call to return this number on a per-engine basis, retrieving the database variable for pgsql, and just returning the constant 256 for MySQL. That way, people like me, who use MySQL and have field names that work within its ample limits, would not be affected.
Views could also provide an API function that would translate a field's name based on this value, so that instead of doing something like:
you could do:
Comment #63
marcp CreditAttribution: marcp commented@Gribnif - which patch did you apply? The one in #40 or the one in #49?
Comment #64
Gribnif CreditAttribution: Gribnif commented@marcp: I didn't apply a patch. I'm using views 6.x-3.0-alpha4, which already includes what I believe is #36.
Comment #65
wiifmEncountered this issue with postgres 8.4 with drupal 6.22 using views 2.16
Original views query (taken from the query display at the bottom of views):
The above query silently failed, note the alias 'node_node_data_field_original_node_data_field_name_field_name_value' -> this is 68 characters long. When running this query directly against postgres, using raw SQL above, the column returned was 'node_node_data_field_original_node_data_field_name_field_name_v', or in other words 63 characters.
With patch #40 applied, this is views new SQL:
Note the absence of the 68 character alias, and the introduction of the MD5.
Regardless of (potential) collisions that the MD5 patch may introduce, it still causes a view that *did not work*, to *work*. So I think this patch is a step forward in that regard.
Keen for this patch to be applied to views, as #40 does address my problem.
Comment #66
Encarte CreditAttribution: Encarte commentedReading the previous comment... About patch in #40:
- For:
- Several reports stating it solved the issue
- No reports saying otherwise
- Against:
- Concern about the possibility of collisions, but no actual reports saying so
- It makes much less readable aliases (a hash), but, according to davidwhthomas in #43, «The SQL query can still be viewed and interpreted in the view edit preview panel.»
- Proposals (with no patch ready for review or even started) for other approaches (e. g. «add a DB API call» in #62 or create a «static counter» in #57).
So, this issue is going on since 2009 and it does have a working patch since 2010. Maybe we should apply it already and deal with related feature requests (readable aliases out of the view edit preview panel) or edge cases with collisions later.
I'm proposing #40 as tested and reviewed by the community. What do you think?
Comment #68
Encarte CreditAttribution: Encarte commentedThe system is always right... Even I can see now that the #40 patch needs some drupalization...
Comment #69
Timusan CreditAttribution: Timusan commentedHey Guys
Is there any further status update on this?
Im still running into this issue with Drupal 7.14 using Views 3.3 running on PostgreSQL 9.1.
Error message that comes back:
SQLSTATE[42712]: Duplicate alias: 7 ERROR: table name "field_collection_item_field_data_field_persoon_ab__field_data_f" specified more than once
Original query:
I know at the heart of this is a PostgreSQL issue, but in the Views plugin code, in the query.default.inc, there is code taking this limit into account, but yet this problem still remains.
Cheers
T
Comment #70
Timusan CreditAttribution: Timusan commentedUPDATE
I tried the patch mentioned in #40, and it does fix the aliasses for the SELECT part of the query.
However, as you can see in the above query, it does not affect the aliasses in the LEFT JOIN statements.
You can easily reproduce this by building a view that takes a field collection as a relation and use two field from that field collection as filters. When you try to use both filters at the same time, the above situation happens.
Cheers
T
Comment #71
dawehnerI'm wondering whether DBTNG in drupal core should care about that in 7.x-3.x, though for 6.x this is in the scope of views to do it.
Comment #72
Jax CreditAttribution: Jax commentedOracle only supports aliases up to 30 chars so this patch could be reworked to accommodate that. Or maybe there should be a way to manually suggest aliases for table names instead of just truncating the alias?
Something like:
It also seems that the first patches only take care of field aliases but ignore table aliases.
Comment #73
dawehnerDon't you already have problems with tables defined by core? For example i guess defining a field and running a simpletest will already exceed the limit of 30 characters. In general it's somehow your own fault if you use oracle :)
Comment #74
dawehnerBtw. this patch simply does not work as it is for 7.x
Comment #75
Jax CreditAttribution: Jax commented@dawehner: I'm using views with non-Drupal tables. Drupal is living is MySQL and there is content integrated from an external Oracle DB. Currently I just fixed it with the first patch and truncating $relationship when creating the table alias. This currently works but isn't an elegant solution.
Comment #76
andypostHit this bug in #1787764: Unknown column caused by orderby alias not matching field alias
Reading the thread I see that views needs better aliasing probably md5() is way but not for oracle which needs shorter hash
Comment #77
andypostTalked in IRC with dawehner and come to conclusion that this should be a part of query class to be overridable for special databases ala oracle, and #49 is a way to go
Comment #78
SeanA CreditAttribution: SeanA commentedBy definition, using a hash means the possibility of collisions. Using a shortened alias with a counter of some kind appended is probably a better way.
Comment #79
Ben Coleman CreditAttribution: Ben Coleman commentedAny progress on this? I'm seeing the same problem as Timusan, on Drupal 7.15, Views 3.3, PostgreSQL 9.1. You can pretty much guarantee getting this if you're using two Field Collection fields as filters or sorts.
Comment #80
dagmarHm, can we move this to the drupal project? Maybe somebody can help there, and if this is still present in the 8.x version, we have now a drupal core bug.
Comment #81
dawehnerAdd tag, i guess this could be solved even on the level of dbtng.
Comment #82
dawehnerLet's move to the database component to see whether someone from the db team has an oppinion whether it's worth to fix on the base level.
Comment #83
Josh Waihi CreditAttribution: Josh Waihi commentedA fix at the database level is not really an option. Debian and Ubuntu compile PostgreSQL with this hard limitation on aliases. I don't see why the aliases that views uses need to be the way they are. They are elongated and hard to read. IMO, Views would be better off using sequential aliases like:
Comment #84
andypostSuppose better scheme for naming to assign a first letter of table with sequental suffix after it. maybe better to use first letters of parts in table name:
Comment #85
dawehner@andypost
This naming scheme though really is hard for the generic approach. Just imagine all the fieldapi tables, for example the following two tables or no rate configuration:
Sure we could try to find a good fitting solution all the time, though it's a problem if you have a non-easy-deterministic way to find table aliases.
Comment #86
dawehnerNot sure whether this actually works, but let's see how much is broken with that. In general i'm totally not convinced by this approach/way to truncate the aliases as they would suck.
Comment #87
Pancho#72 / #73
Pondering the decision between the portability and DB-abstraction way vs. optimizing for the most common DB backend, both had their pros and cons, but we decided for portability and DB-abstraction. Now as a consequence we should aim for maximum portability, and of course that should include Oracle, even if there's still a way to go until we're fully compatible out of the box.
That clearly means we should get along with a maximum length of 30.
While both the hash-only and the truncate-and-index approaches are unique, they're both not self-descriptive (the first never, the latter not necessarily).
Therefore I believe we should revisit Damien McKenna's standard abbreviations approach in #44. We might even be able to leave out the underscores, so it gets really compact while still descriptive. Only if X is too long, we'd need to truncate and index X to avoid going over the 30 characters limit.
Comment #88
idebr CreditAttribution: idebr commentedd7 version of #86
Comment #90
SeanA CreditAttribution: SeanA commentedRe #87: No. Hashes are not unique.
Comment #91
dawehner#86: drupal-571548-86.patch queued for re-testing.
Comment #92
dawehnerIt does not make sense to use the drupal version because we just care about ascii chars.
Comment #94
nithinkolekar CreditAttribution: nithinkolekar commentedsame problem here as @Timusan and @coleman with drupal 7.23 ,views 7.x-3.7
Comment #95
nithinkolekar CreditAttribution: nithinkolekar commentedtag "field collection item" is added.
When field collection item is added as relationship to views this will cause
NOTICE: identifier "field_collection_item_field_data_field_actors__field_data_field_actors_list" will be truncated to "field_collection_item_field_data_field_actors__field_data_field" and leads to SQLSTATE[42712]: Duplicate alias: 7 ERROR: table name.
In above example field_data_field_actors is field collection item and field_data_field_actors_list is normal textfield inside fileld collection.
example
Movie(Normal node) ----------------------Inception
-|- Actors(fieldcollection item)------------
-----|--Actors List(multivalue textfiels)----Dicaprio
-----|------------------------------------Tom
Comment #96
Drupa1ish CreditAttribution: Drupa1ish commentedWorks on PG 9.3, View 3.7, D 7.26
Comment #97
DamienMcKennaThis version is similar to #96 only a) it will apply properly to the codebase, b) it takes the last 60 characters of the alias name instead of the first 60.
Comment #98
Liam MorlandRelated: #998898: Make sure that the identifiers are not more the 63 characters on PostgreSQL
Comment #99
stefan.r CreditAttribution: stefan.r commentedThis has been fixed in Views itself already -- not sure if we need to port the fix to the postgresql driver anymore as this should only affect contrib modules, very rarely?
Comment #100
steinmb CreditAttribution: steinmb commented@stefan.r Not sure I follow you. The changes that make sure they do not overflow the 63 char limit is already committed to the PostgreSQL 8.x core driver, what we do not need/should do, is to have special code in views regarding Postgres?
Comment #101
stefan.r CreditAttribution: stefan.r commented@steinmb I don't think we fixed table aliases yet in the core patch (#998898: Make sure that the identifiers are not more the 63 characters on PostgreSQL), this only affected indexes/constraints/primary keys. There is however already some special code in Views that makes sure we do not overflow the 63 char limit! :)
From
core/modules/views/src/Plugin/views/query/Sql.php
:Comment #102
steinmb CreditAttribution: steinmb commentedAh. Thank you for clarifying. I was, as usual, confused :)
Comment #103
steinmb CreditAttribution: steinmb commentedAh. Thank you for clarifying. I was, as usual, confused :)A 504 gave me a double post, sorry.
Comment #104
nithinkolekar CreditAttribution: nithinkolekar commented@stefan.r is that core patch fixes issues when views has field collection relationship ? (#70, #79, #95)
Comment #105
jhedstromComment #106
ravi.khetri CreditAttribution: ravi.khetri commentedRerolled.
Comment #107
siva_epari CreditAttribution: siva_epari commentedAbove rerolled patch has:
1. Empty spaces introduced at the end of line 286.
2. New lines before line 285 & after 286 removed.
Attaching proper reroll.
Comment #108
robertwb CreditAttribution: robertwb commentedCreated a issue and D7 backport patch for this issue. https://www.drupal.org/node/2492833#comment-9947839
Comment #109
mgiffordRe-uploading patch for the bots.
Comment #114
RoSk0Comment #115
dagmar#998898-58: Make sure that the identifiers are not more the 63 characters on PostgreSQL Introduced a method:
ensureIdentifiersLength
for Drupal 8. Are we sure this is still an issue for D8?If this is still an issue, the proposed solution in #109 is not accurate and should use an approach similar to the implemented in #998898.
Comment #117
yce CreditAttribution: yce at Pronovix commentedHi,
Looks like it's not enough to cut the alias at 60 chars, because that could cause duplicate aliases.
I've created a patch for 7.x version that tries to solve it.
Comment #119
aalden CreditAttribution: aalden commentedI found that patch #107 wasn't sufficient when creating a view when I had more than one relationship involving taxonomy term fields within paragraphs on a node so I extended the patch.
Comment #120
Pancho@yce:
Thanks for your contribution!
This is however an issue against Drupal core 8.
Patches against Views 7 are welcome in #2492833: truncated identifiers with more than 63 chars, causing Views to break (D7 Backport).
Comment #123
ncKlan CreditAttribution: ncKlan commentedI had the issue on a Drupal 8.9.2 that I'm building for a client, because it had a lot of long field and table names, which resulted in that just cutting it still gives the error.
Here I instead shorten the base table name before creating the relationship. Here only the first letters for the base table is joined together to make room for field tables and column aliases.
This also makes that the sql preview gets shorter and prettier in the views edit.
Comment #124
ncKlan CreditAttribution: ncKlan commentedI found the issue still persists after cutting the length down if the fields.
So instead of cutting down I made a patch which takes the first letters of the base table names and uses that as bases for the alias.
This also makes the preview in views edit easier to look though.
Comment #125
apadernoComment #126
Liam MorlandPatch failed to apply.
Comment #127
ankithashettyRe-rolled the patch in #123. Kindly review.
Thank you!
Comment #129
apadernoComment #130
papajo CreditAttribution: papajo as a volunteer commentedI had this issue with Druapl 8.8.10.
The patch pgsql_views_alias_571548-123-d8.patch works but there are risks of table name collisions and some warning (eg 2 successive "_").
Comment #131
papajo CreditAttribution: papajo as a volunteer commentedI had this issue with Drupal 8.8.10.
The patch pgsql_views_alias_571548-123-d8.patch works fine but there are risks of tables name collisions and some warning (successive '_' in the original name).
Comment #132
apadernoComment #133
LendudeI tried to reproduce this in a test, but I can't get this to fail on Postgres. Am I not reading the steps to break right?
Comment #134
daffie CreditAttribution: daffie commented@lendude As requested have a looked at the issue. First: Your test does not fail because the "real table" name is much shorter then 63 characters.
Second: The PostgreSQl driver makes sure that all indexes, constraints, primary keys and sequences have a name that is save. Even when that name is longer then 63 characters. It does not do that for table names, column names and aliases. When you create a table with a name that is longer then 63 characters it just uses the first 63 characters for the table name. I think that the problem for views may come when you have 2 or more table names that are longer then 63 characters and are for the first 63 characters the same. My question to you is: is that a problem for views or not?
Comment #135
apadernoYes, the issue described here is that the table names/aliases are truncated to 63 characters.
Comment #136
robertwb CreditAttribution: robertwb commented@daffie - the problem is absolutely with Views. Views creates it's own aliases for tables during its query creation. In order to test appropriately one would need to create a view with sufficient complexity (i.e. multiple joins) and sufficiently long base table names, that the aliases that Views automatically generates exceeds 63 characters.
This can be achieved via these steps:
# Create a new content node type
# add an entity reference field with a long name like "verbosely named entity reference field"
# create a view to show nodes of this content type
# Add an entity reference relationship in the view based on the "verbosely named entity reference field"
# Add a second entity reference relationship in the view based on the "verbosely named entity reference field"
Execute the view. The name will be truncated by this patch to 61 characters.
Comment #137
DamienMcKennaPut another way: given that the test-only patch passes on PostgreSQL instead of failing, is it possible that newer releases of PostgreSQL have resolved this problem?
Comment #138
Liam MorlandThe current PostgreSQL Limits say "identifier length: 63 bytes". It also says "can be increased by recompiling PostgreSQL". Some people could be testing in versions compiled to allow longer.
Comment #139
DamienMcKennaSo do the tests need to check for that setting in PostgreSQL?
Comment #140
Liam MorlandIt would be best if the d.o. testing infrastructure just doesn't customize that setting. People on their own might have longer allowed, but it would get caught when testing happens here.
Comment #141
daffie CreditAttribution: daffie commentedAs Drupal we cannot rely on user recompiling their PostgreSQL database. For Drupal it must work with the 63 character limit.
Comment #142
RoSk0Completely agree with #141.
Can confirm that issue is still present on Drupal 9.1.3 & PostgreSQL 11.7.
Comment #143
valeriap CreditAttribution: valeriap as a volunteer commented@papajo I tried your patch #130 and it was working in one case but failing in a case when both parts of the alias were long, so I slightly modified your patch to pass both parts of the alias string to the shortenTableAlias function. This works for me, but I'm not a Drupal Views expert so I hope it doesn't break anything else.
Comment #144
apadernoComment #145
anmolgoyal74 CreditAttribution: anmolgoyal74 at OpenSense Labs for DrupalFit commentedComment #147
mondrakeOutside of core, Oracle 11 has a limit of 30 chars for identifiers, including aliases.
IMHO we should reconsider, as suggested in some comments, trying to solve this at the database API level, as part of
escapeAlias()
implementation, using hashing techniques to reduce the alias length, encoding the input during SQL preparation. Then, decode the hashed alias back while fetching records.Comment #148
daffie CreditAttribution: daffie commentedThey have the same problem in the migrate module.
Comment #149
mondrakeFiled #3200743: [WIP] Decouple identifier management from database Connection, introduce an IdentifierHandler class.
Comment #150
bluegeek9 CreditAttribution: bluegeek9 as a volunteer commentedI tried patch 145 and it resolved the character length limitations, but I different errors about non unique aliases. I hash the $table_name and use the first 16 character to ensure uniqueness.
Comment #151
Suresh Prabhu Parkala CreditAttribution: Suresh Prabhu Parkala at Specbee commentedRe-rolled patch. Please review.
Comment #153
bluegeek9 CreditAttribution: bluegeek9 as a volunteer commentedIt uses a hash to ensure uniqueness, and then reverts the hashed alias in the postExecute().
Comment #154
Abhijith S CreditAttribution: Abhijith S as a volunteer and at Zyxware Technologies commentedFixed custom commands fail in patch #153
Comment #155
bluegeek9 CreditAttribution: bluegeek9 as a volunteer commentedPatch 153 was using a php8 function, str_starts_with; replaced with strpos($property, $this->shortAlias) === 0) .
Comment #156
neibo CreditAttribution: neibo commentedbluegeek9
#155
This works without a function postExecute().
And it doesn't work with it if the result has already been cached. I see empty fields in the table.
What happens if I delete postExecute()?
Comment #160
Satyanarayan Reddy CreditAttribution: Satyanarayan Reddy as a volunteer and at Wipro Technologies commentedUploading working pacth file Drupal version 9.41 and PostgreSQL version 13
Comment #161
pooja saraah CreditAttribution: pooja saraah at Srijan | A Material+ Company for Drupal India Association commentedFixed Failed Commands #160
Attached interdiff
Comment #163
Liam MorlandThanks for the patch!
Comment #164
jweowu CreditAttribution: jweowu at Catalyst IT commentedI don't have sufficient understanding of Views to say where it's failing, but the approach used in #155 (and subsequent rerolls) is insufficient. It worked for the View I was working on at the time I applied the patch, but it turned out to be responsible for breaking a different one. The broken View was using aggregation/grouping, which might be relevant.
I didn't know where to start with adapting that patch to work in both scenarios, so I've taken a different approach.
I looked for every piece of code in
core/modules/views/src/Plugin/views/query/Sql.php
which seemed to be generating an alias value arbitrarily, and I put those through a sanitizer function so that it produces a safe alias value in each case.I've done something similar to #155 in generating a short hashed prefix (I used
crc32
instead of truncating asha1
value, just because it's already short).I haven't been remotely so aggressive with the length limit (#155 set that to a tiny 19 chars). I assume that was for the benefit of certain other database products? I'm using Postgres which has a 63 char limit for aliases, so I just kept the 60-char limit that Views was kinda-sorta trying (but failing) to use already.
I've tested all the existing Views on my particular site with this in place. I'm pretty confident I have not exercised all of the affected code paths in that process, so "works for me" is all I can say right now.
Comment #165
pooja saraah CreditAttribution: pooja saraah at Srijan | A Material+ Company for Drupal India Association commentedFixed Failed Commands #164
Attached interdiff
Comment #166
jweowu CreditAttribution: jweowu at Catalyst IT commentedThanks for the updates poojah saraah. I had no idea the testbot was nowadays insisting on dictionary words only in identifier names. (That must have been a fun change when it was implemented!?)
So the test failure we're seeing now is expected -- it's testing a truncated alias, so it's seeing the old style (simple truncation) rather than the patched/uniquified style.
The failed assertion in
testNoDataTableRelationship()
incore/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php
is:which is exactly 60 characters. It's not immediately obvious what
field_test_data_i
was originally, as nothing starts with all of that; but grepping forfield_test_data
turns up lots of relevant things, so we're looking for "something which starts with 'i'" which really doesn't narrow things down as much as I'd like. Maybe it was "id"?In any case, I believe the sanitizer needs to be available to the test code for this, as at present it looks to me like the test contains a hard-coded assumption that this previous code was executed:
As I can't tell from perusing the code what that alias would have been originally, I also can't tell what we would need to pass to the sanitizer in order to fix the test.
The test in question originates here:
https://git.drupalcode.org/project/drupal/-/commit/b58ab8cef820d11e0305e...
Comment #167
jweowu CreditAttribution: jweowu at Catalyst IT commentedI should note that I also looked at #147 and tested performing the sanitization in that
escapeAlias()
method (which certainly sounded good, albeit also increasing the scope of the issue beyond only Views), but I still saw the same long aliases from Views making it through to Postgres and causing errors, so evidentiallyescapeAlias()
isn't guaranteed to process all aliases (although it was processing some of them, so the code was working where it could).Comment #168
rossidrup CreditAttribution: rossidrup commentedI applied the 164 and also 165 and it still gives me an error when I turn on aggregation in views
Comment #169
jweowu CreditAttribution: jweowu at Catalyst IT commentedThat original
field_images_
(when it selectsc2548530755iations__commerce_product_variation__field_images"."field_images_" AS "c2393567943rce_product_variation__field_images_field_images_"
) is not an alias; so yes -- my patch has no effect on whatever is causing that.It may very well be a different truncation bug, though. See if you can discover where that is happening, and then open a separate issue for that (and link to it from here).
Comment #171
steinmb CreditAttribution: steinmb as a volunteer commentedComment #172
xurizaemonComment #174
pebosi CreditAttribution: pebosi commentedCould you add a re-rolled patch for 10.1 and 10.2 ?
Comment #175
jweowu CreditAttribution: jweowu at Catalyst IT commented#165 applies just fine to 10.1. You can check 10.2 and let us know if it doesn't apply.
Comment #176
jweowu CreditAttribution: jweowu at Catalyst IT commentedFollowing up my comments in #166:
I believe that guess is correct...
EntityReferenceRelationshipTest::setUp()
does this:Which looks like it's making
field_test_data
a reference to aentity_test_mul
entity, andfield_data_test
a reference to aentity_test
entity.Both of those entity classes declare:
So
id
looks like the only property it might be if the name is just a concatenation of field name and property key.And finally, my interpretation for the truncated name is consistent with other appearances of that comment for the
field_data_test
field:So I think the way forward is:
Comment #177
jweowu CreditAttribution: jweowu at Catalyst IT commentedSo let's give that a whirl (against 10.1.x initially).
----
That test gave us:
Which is complaining about the pre-existing (not part of this patch) code in
Drupal\views\Plugin\views\query\Sql::queueTable()
:The "always exists" is certainly accurate, but on first look I'm not convinced by the "is not nullable" part. PHPStan must have a reason for claiming otherwise (and I'd tend to assume it's right and I'm wrong), but the reason is sufficiently non-obvious that I can only question the value of eliminating safeguard code on that basis.
By my reading, if we had two calls to
queueTable($table, $relationship = NULL, JoinPluginBase $join = NULL, $alias = NULL)
using the same table and relationship arguments, and if the second of those calls had a NULL alias argument, then that null could reach the isset() call. Joining to a database table twice with different aliases and join conditions is 100% a valid thing to do in a SQL query (I wouldn't even call it uncommon), so I see no reason why in principle this couldn't happen.It does seem like an empty string alias shouldn't be considered valid, though (especially as the alias is used as an array key, and null array keys are coerced to empty strings), so I'll change that
!isset()
toempty()
so that we can catch that case and hopefully prevent PHP Stan from asking us to delete a pre-existing safeguard.Comment #178
jweowu CreditAttribution: jweowu at Catalyst IT commentedComment #179
jweowu CreditAttribution: jweowu at Catalyst IT commentedAttempting to work around the PHP Stan complaint.
Comment #180
jweowu CreditAttribution: jweowu at Catalyst IT commentedRe-roll of #179 for 10.2.x and 11.x.
(The testbot seems generally unhappy right now, so we'll need to re-test later, once https://www.drupal.org/node/3060/qa has a green light.)
Comment #181
smustgrave CreditAttribution: smustgrave at Mobomo commentedRecommend turning to MR as patches are being phased out.
But appears to have several test failures.
Also issue summary should follow standard issue template.
Thanks!
Comment #182
jweowu CreditAttribution: jweowu at Catalyst IT commented> Recommend turning to MR as patches are being phased out.
The MR workflow at drupal.org continues to not provide persistent immutable patch URLs which is hugely problematic when it comes to referencing patches externally, so I'm sure the old method isn't going anywhere while that flaw remains. So long as the traditional patch files are supported I'll prefer to keep using them.
> appears to have several test failures.
Of the tested Drupal versions (10.1, 10.2, 11.x) only 10.1 seems to be currently passing its own tests (sans patches), and against that version this patch passed testing too. AFAICT the vast number of test failures on 10.2 and 11 are entirely unrelated to this patch, and there doesn't seem any point in re-testing until those branches start passing tests on their own. (From a brief look, the problems appear to be related to disk-space on the test servers rather than code; but regardless, there seems little purpose to re-queueing tests just now.)
> Also issue summary should follow standard issue template.
Indeed, that would be good.
Comment #183
jweowu CreditAttribution: jweowu at Catalyst IT commentedComment #184
poker10 CreditAttribution: poker10 at ActivIT s.r.o. commentedPlease follow this issue #3412417: Disable DrupalCI testing regarding the DrupalCI deprecation.
That said, you will be able to upload patches like any other files in the future, but no other tasks regarding testing/DrupalCI would work after specific date on these files.
Comment #187
jweowu CreditAttribution: jweowu at Catalyst IT commentedBased on that issue, I'm not confident that the 10.2.x and 11.x core branches are going to pass their traditional testing anytime soon, so I've made a MR for testing #180 on those versions.
Comment #188
smustgrave CreditAttribution: smustgrave at Mobomo commentedCan you update to 11.x as the target. It can be backported on commit but has to land on 11.x first.
But see 10.2 is green so that’s good
Comment #190
jweowu CreditAttribution: jweowu at Catalyst IT commentedUnless I'm missing something, the MR workflow more or less necessitates separate branches for testing against each version of Drupal as it's no longer a simple patch that's being applied, so I've created 10.2.x and 11.x branches for this.
Comment #191
jweowu CreditAttribution: jweowu at Catalyst IT commentedComment #192
jweowu CreditAttribution: jweowu at Catalyst IT commentedWell, there's a MR test failure for "PHPUnit Functional Javascript 1/2" which recurred on a retry, but there's no Javascript involvement here, so I'm setting this back to Needs Review.
Edit: Now re-tested without seeing that false-positive failure.
Edit2: Actually, it's still happening for some pipeline runs.
Comment #193
smustgrave CreditAttribution: smustgrave at Mobomo commentedHiding patches for clarity
Issue summary appeared to be updated in #183 so removing that tag
Comment #194
xurizaemon@jweowu the JS test failure is performance related, suggest to hit Retry on the job @ https://git.drupalcode.org/issue/drupal-571548/-/jobs/713304 if you have a button there for that (I don't).
Reviewing the issue description and considering "User interface changes", are there impacts on the generated aliases which should be considered here? Places where this might surface could be somewhere that a generated identifier before and after this change differs, including in:
- Custom code which references the alias
- Templates referencing aliases
- Exposed query parameters (eg sort=) which reference aliases
Comment #195
jweowu CreditAttribution: jweowu at Catalyst IT commentedYes, at minimum the alias argument can be NULL. I can't recall offhand whether there are other possibilities, but there's at least that one, and the only thing the function can cope with is a string, so I think
is_string()
is the sensible guard.Comment #196
smustgrave CreditAttribution: smustgrave at Mobomo commentedFor the open thread
Comment #197
jweowu CreditAttribution: jweowu at Catalyst IT commentedComment #198
jweowu CreditAttribution: jweowu at Catalyst IT commentedI don't know why it auto-marked that as a draft, but I'd hazard a guess that it was complaining about the fixup commit (which I think is dumb, because this then means I need to force-push changes, rather than trivially squashing the fixups once it's reviewed and without imposing force-pushes on anyone). Anyhow -- no actual changes there.
Comment #199
jweowu CreditAttribution: jweowu at Catalyst IT commentedThat was just a phrasing tweak for the code comments.
Comment #200
smustgrave CreditAttribution: smustgrave at Mobomo commentedRan test-only feature so removing that tag
Left 2 small comments on MR
Issue summary mentions a TODO to add steps to reproduce
Tagged for a simple change record for the new sanitizeAlias feature.
Believe this is super close