Posted by xjm

The documentation states:

Rather than using a textfield or weight field, this form depends entirely upon the order of form elements on the page to determine new weights.

Because there might be hundreds or thousands of taxonomy terms that need to be ordered, terms are weighted from 0 to the number of terms in the vocabulary, rather than the standard -10 to 10 scale. Numbers are sorted lowest to highest, but are not necessarily sequential. Numbers may be skipped when a term has children so that reordering is minimal when a child is added or removed from a term.

However, the weight field of term_data is implemented as a signed tinyint in the taxonomy_schema(), which would mean it can only range from -128 to 127, and I don't see any function in taxonomy.module to update the schema. Indeed, I tested it for a vocabulary with 150 terms or so, and ordering stops working after term weight 126 (all heavier terms are inserted as 127). I understand this could be corrected with contrib, but the core documentation is incorrect given the current functionality.

Comments

xjm’s picture

jhodgdon’s picture

Title: Documentation problem with taxonomy_overview_terms_submit » taxonomy_overview_terms_submit() assigns weights that may exceed database field size
Version: 6.x-dev » 7.x-dev
Component: documentation » taxonomy.module

Wow, good catch! This is a bug in the code, in my opinion, not the documentation (although if the code is not going to be fixed for some reason, the documentation is clearly wrong compared to the documentation).

The bug being that if you have more than 125 taxonomy terms in a given vocabulary, taxonomy_overview_terms_submit() will assign weights that exceed the tinyint size of the weight field in the database. See
http://api.drupal.org/api/function/taxonomy_overview_terms_submit/7
http://api.drupal.org/api/function/taxonomy_schema/7

Actually, you could run into trouble with even fewer than 126 terms, because (if the current doc header is correct about that) the numbering might not be sequential.

It's a bug in Drupal 7, but probably should be backported to the next release of Drupal 6 as well? It seems serious to me. The fix is easy: change the taxonomy schema so that the weight field is not a "tiny" integer.

jhodgdon’s picture

Other possible places in the Drupal 7 code that might have this problem are from fields (aside from "flag" or boolean fields) in the Drupal database that are defined to be type="int", size="tiny". Here is what I found in the Drupal 7 code base:

- block module/block table/weight field
- contact module/contact table/weight field
- filter module/filter table/weight field
- filter module/filter_format table/weight field
- poll module/poll_choice table/weight field
- profile module/profile_field table/weight field
- taxonomy module/taxonomy_term_data table/weight field
- taxonomy module/taxonomy_vocabulary table/weight field
- upload module/upload table/weight field

These mostly apply in Drupal 6 as well, with minor changes (such as table names that have changed).

I haven't yet examined the form submit code for these modules to see whether they have the same problem as taxonomy_overview_terms_submit() either, just noting that these are tables with tinyint weight fields, which seems like at least a potential problem.

jhodgdon’s picture

Priority: Normal » Critical

Upon further reflection, this is probably a critical bug.

chx’s picture

suncatch asked me how big our terms table is, it's less than a million, a normal int will do.

jhodgdon’s picture

Well then, probably all of the tables listed in #3 should be changed so their weight fields are int/medium or int/normal rather than int/tiny. In both Drupal 6 and 7.

Hmmm... http://drupal.org/node/159605 says that medium int is 3 bytes in MySQL, 4 bytes in PostgreSQL.... That's enough to go to 8 million, so that should be OK (see http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html). "int/normal" is 4 bytes on both platforms.

catch’s picture

Title: taxonomy_overview_terms_submit() assigns weights that may exceed database field size » Weight fields should be int, not tinyint
Component: taxonomy.module » base system

Agreed, and this should be done across the board. Since it's a schema change would be nice to get it in soonish. This is only critical for taxonomy and possibly profile since the rest are much less likely to hit the restriction, but since contrib modules will likely copy and paste schema from places it's better to be consistent here.

asimmonds’s picture

Status: Active » Needs review
StatusFileSize
new8.3 KB

First stab at a patch to increase the weight columns to 'normal' for the tables listed in #3.

Uploaded so the testbot can test.

- Does 'normal' have to specified? I think this is the default if you don't specify a size (ie menu_links table)

@ #drupalsouth

dave reid’s picture

Status: Needs review » Needs work

I think we can just exclude 'size' => 'normal' since that's the default? And we don't need to drop and define all the indexes again?

asimmonds’s picture

Status: Needs work » Needs review
StatusFileSize
new7.88 KB

db_change_field() api help has:

IMPORTANT NOTE: To maintain database portability, you have to explicitly recreate all indices and primary keys that are using the changed field.

I am just re-creating the indexes where the weight field was included.

Patch updated to remove the size => 'normal'. Pretty certain that is the default, on mysql 5.0 'normal' is int(11) and leaving it out is int(11)

dries’s picture

This looks good to me, but let's see what the test bot says (currently in 'test request sent').

jhodgdon’s picture

How about putting in an explicit size rather than just removing 'size' => 'tiny' in all of those db columns?

dave reid’s picture

@Dries Test bot won't work until #693362: taxonomy_form_all() is dangerous is rolled back as well.

dries’s picture

jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community

Looks like this is RTBC then? My comment in #12 was negated by #9 & #10.

webchick’s picture

Version: 7.x-dev » 6.x-dev
Priority: Critical » Normal
Status: Reviewed & tested by the community » Patch (to be ported)

I didn't notice any menu module hunks in here, but checked and those weight fields are already set to ints. I have a feeling this fix will solve a couple of other issues in the queue now.

Committed to HEAD. Marking for backport, depending on how Gábor feels about this.

RonD’s picture

I wish to encourage Gabor to backport this fix.

We are building out a site in 6.15 and encountered this issue with blocks yesterday. I found http://drupal.org/node/565220#comment-2161254 yesterday and found this issue today while checking for duplicates before posting a new issue.

grendzy’s picture

I also encountered this today on a D6 site with a large number of blocks. They could be re-ordered with tabledrag, but saving the form had no effect.

NaX’s picture

+1 for the backport

I just run into this problem with taxonomy on a large vocabulary. If you have a large vocabulary of more than 127 items you are forced by this limitation to sort alphabetically or at least from the 127th item onwards. In my case Countries grouped by continent. I was unable to have a No Region item last, until I manually changed the column.

jhodgdon’s picture

Gabor doesn't normally backport fixes. Someone in the community writes the patch, someone else in the community reviews and tests the patch sufficiently to mark it "reviewed and tested by the community", and then Gabor commits it if he agrees it is a good patch. That is the process.

So, if you are interested in getting this fix into Drupal 6, the next step is for someone to scan through the hook_schema() functions in Drupal 6 core, find everywhere that weight fields are tinyint instead of int, and make a patch to change them. In Drupal 6, this will also require update functions, besides changing the schema definition, similar to what was done in Drupal 7 patch in #10 above.

Anyway, it isn't the exact patch from #10, but it should be somewhat similar.

cyberwolf’s picture

Subscribing. Also encountering the weight limitation, on the terms of a taxonomy vocabulary.

Dublin Drupaller’s picture

I'm having the same problem in drupal 6.x specifically with blocks but I see that the patch in #10 covers a lot of other tables which would be useful if it was rolled back.

benshell’s picture

Status: Patch (to be ported) » Needs review
StatusFileSize
new6.16 KB

Here is a D6 backport of this patch, ready for testing. At least the taxonomy part of this patch is critical for many sites.

zilverdistel’s picture

Tested the patch in #23, seems to work for me ...

EvanDonovan’s picture

Will test this soon. Ran into this today with profile.module (shudder!) fields...

chrisarusso’s picture

#23 worked well for me too. Thanks benshell et al.

cydharttha’s picture

Thanks much, was beating my head against an Ubercart install with a large catalog (taxonomy). Updating DB schema solved it.

Mac Clemmens’s picture

Thanks, Ben! Prior to this patch, I kept running into issues and have had to increase the size of the int field manually.

xjm’s picture

Status: Needs review » Reviewed & tested by the community

We RTBC here (based on #24-28)?

EvanDonovan’s picture

Sorry didn't actually test. But others seem to have had success...

gábor hojtsy’s picture

Uhm, why do we need to have separate code blocks here for MySQL and PostgreSQL? Also, how should we coordinate fixes for this in the D7 update path? I assume the update will not be a problem except unneeded code runs. Anybody verified that?

gábor hojtsy’s picture

Status: Reviewed & tested by the community » Needs review
pgillis’s picture

Subscribe

Foonaka’s picture

Title: Weight fields should be int, not tinyint » #23 Worked for me, too!

If there's any noobies out there, be sure to run Update.php after applying the patch. I about beat myself over the head until I remembered that I had not done that yet. Once I did, it worked like a charm!!! Thanks to benshell for backporting that patch for D6.

Foonaka’s picture

Title: #23 Worked for me, too! » Weight fields should be int, not tinyint

Sorry, I accidentally changed the title of this topic! Hopefully this will change it back...

brulain’s picture

#8: 612870-increase-weights.patch queued for re-testing.

harrrrrrr’s picture

any progress?

xjm’s picture

See #32 for the questions that still need to be addressed.

forbesgraham’s picture

Subscribed!

xjm’s picture

@forbesgraham: You do not need to post "subscribe" comments any more. There is a green "Follow" button in the upper right corner of issues.

aloyr’s picture

here is a thought for the first part of your question: I am not all that familiar with postgresql, but it seems that it handles alter column differently than mysql, so drupal 6 has an api function to deal with that kind of stuff. of course drupal 7 implements the database layer pretty differently than 6 and doesn't have that api call anymore.

can this change for drupal 6 be moved upstream?

Status: Needs review » Needs work

The last submitted patch, 612870-increase-weights-d6.patch, failed testing.

xjm’s picture

See #16. This is already fixed in D7.

mrfelton’s picture

Status: Needs work » Needs review
StatusFileSize
new5.26 KB

Patch updated to apply against latest D6 git code.

fietserwin’s picture

Status: Needs review » Reviewed & tested by the community

In reply to the concerns mentioned in #32:

Separate lines of code for postgress versus mysql: I guess these are not needed. Drupal 6 does have change_db_field() as well, so the D6 patch could be very similar to the D7 patch. However, the patch as posted also works as already confirmed before by others and now once more by myself (site with more than 255 blocks). So the discussion is not about whether it works or not, but about more subjective terms like cleanliness, maintainability, understandability. Regarding these, I would like to mention that it doesn't really matter in this case.
- This code won't be maintained. Errors in hook_update() can often only be solved by writing yet another hook_update,not by changing the code itself.
- This code was readable and understandable for me.

Moreover, considering D6 is already far in the maintenance phase of its life cylce, chances that this code needs to be refactored are minimal. And we all know that if I would put this issue back by rewriting the patch, it will not reach RTBC for the next year.

So, the choice is: accept this possibly slightly inferior but tested, reviewed and working patch, or accept that this issue will "never" reach RTBC and that from time to time Drupal users will loose many hours of debugging and searching before they stumble upon this issue.

D7 update: I tested these steps:
- clean 6.26 install
- applying the patch from #45
- run update.php
- install 7.14
- run update.php from 7.14
No problems at all. Database is as it should be.

Furthermore: I reviewed the hook_update()s that will be run between the updates in this patch and the "corresponding" hook_update()s in the D7 .install files: none of these resets, touches or assumes anything about the size of the weight field. So no problems here either.

sunward’s picture

this patch (#45) works.

But to have to redo the patch with every update is just asking for trouble. It is also getting annoying having to redo the taxonomy for the catalog (getting big for an ecommerce site)

Any chance this could be made permanent or as a module?

Jenechka’s picture

Thank you! Patch from #45 works!

jvieille’s picture

Any hope? 3 years old bug...

jvieille’s picture

Issue summary: View changes

Removing myself from the author field to unfollow the issue. --xjm

pianodavid’s picture

Issue summary: View changes

Hi, any hope of getting this commited to D6?

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 45: 612870.45-increase-weights-d6.patch, failed testing.

Status: Needs work » Closed (outdated)

Automatically closed because Drupal 6 is no longer supported. If the issue verifiably applies to later versions, please reopen with details and update the version.