Because views_schema_1() is called directly in views_update_6000(), the database schema is immediately up-to-date when update 6000 is run, and any subsequent updates which modify the schema are at risk of failing.

For example, update 6003 adds a 'new' unique key which already exists.

I think this views.install file needs a separate views_schema_6000() which defines the schema as it was originally, so that all of the subsequent updates can apply cleanly. This then would be the one used by views_update_6000().

Comments

jweowu’s picture

Adding error messages for searchability:

Update 6003:
user warning: Duplicate key name 'name' query: ALTER TABLE views_view ADD UNIQUE KEY name (name) in [...]/includes/database.mysql-common.inc on line 403.

Update 6006:
warning: Table 'cache_views_data' already exists query: CREATE TABLE cache_views_data ( `cid` VARCHAR(255) NOT NULL DEFAULT '', `data` LONGBLOB DEFAULT NULL, `expire` INT NOT NULL DEFAULT 0, `created` INT NOT NULL DEFAULT 0, `headers` TEXT DEFAULT NULL, `serialized` SMALLINT NOT NULL DEFAULT 1, PRIMARY KEY (cid), INDEX expire (expire) ) /*!40100 DEFAULT CHARACTER SET UTF8 */ in [...]/includes/database.inc on line 517.

jweowu’s picture

I think this views.install file needs a separate views_schema_6000() which defines the schema as it was originally, so that all of the subsequent updates can apply cleanly. This then would be the one used by views_update_6000().

Actually, looking at the comment for views_schema_1(), this may be precisely what this function was intended for: "Views 2's initial schema; separated for the purposes of updates."

If I'm reading this rightly, the problem is that views_schema_1() was subsequently modified when it should never have been.

views_schema() should possibly have started out as a replica of views_schema_1(), rather than a function which returns it?

jweowu’s picture

Status: Active » Needs review
StatusFileSize
new5.99 KB

Revision 1.37 was where this split originated, so I've made a patch (against 6.x-2.6) which uses that version of views_schema_1() and uses the 6.x-2.6 version of views_schema_1() as views_schema()

jweowu’s picture

StatusFileSize
new5.93 KB

Modified views_schema_1() as per revision 1.44 (see http://drupal.org/node/357368 )

The differences between views_schema_1() and views_schema() are now exactly what the hook_update function have changed, so I think this patch is good.

merlinofchaos’s picture

I think what I'd intended to have and didn't end up doing is to have views_schema_1() and then replace that with views_schema_2() and change views_schema() to always use the most current one. So I'd prefer if views_schema() just passed through to the most current. At least, that's what I intended and it seems like it'd be better for history.

jweowu’s picture

That seems kinda verbose (and possibly error-prone), to be honest. To my mind that's what CVS is for (if the changes in question aren't clear from the hook_update functions).

OTOH I don't spend any time with this code base, so I won't pretend my opinion counts for much here :)

Let me know if you'd like a new patch adding the additional schemas.

merlinofchaos’s picture

Well, views_schema_2 can call views_schema_1 and just make changes to it. The reason I wanted to do it this way was so that I could just use the schema functions in updates rather than having to replicate older schema bits in update functions. It's an experimental choice.

jweowu’s picture

StatusFileSize
new5.76 KB

Oh I see. Yes, that makes sense to me now :)

Patch attached.

jweowu’s picture

StatusFileSize
new6.59 KB

Possible improvement: Use something along the lines of install.inc's drupal_get_schema_versions() to automatically determine the latest views_schema_(n) in hook_schema()

/**
 * Implementation of hook_schema().
 */
function views_schema() {
  $views_schema = views_current_schema();
  return $views_schema();
}

/**
 * Find the current version of the database schema.
 * @return
 *   The name of the views_schema_<n> function, for the highest available <n>.
 */
function views_current_schema() {
  $schemas = array();
  $functions = get_defined_functions();
  foreach ($functions['user'] as $function) {
    if (strpos($function, 'views_schema_') === 0) {
      $version = substr($function, strlen('views_schema_'));
      if (is_numeric($version)) {
        $schemas[] = $version;
      }
    }
  }
  sort($schemas, SORT_NUMERIC);
  return 'views_schema_'. array_pop($schemas);
}

Here's the patch with this integrated, if it's considered useful.

jweowu’s picture

StatusFileSize
new7.32 KB
new6.56 KB

It occurred to me that I could also remove the requirement for each schema update function to explicitly name the previous one as a starting point, if I simply statically cached the sorted array of updates. Each call would then pop the correct function name off the stack.

I'm attaching a couple of new patches. The first is the simpler version, which works just fine if all we want is the latest hook_schema() or the original hook_schema_6000(), but which breaks if any other specific version is asked for.

I'm not really sure if that's ever going to happen, but I implemented another variant which resolves the problem by passing __FUNCTION__ to hook_schema(), so that it knows where to begin.

eriktoyra’s picture

Is it safe to ignore these warnings when updating from 5.x to 6.x? I have analyzed the SQL queries and the database tables seems to be OK after the update even with those warnings above.

Anonymous’s picture

O_o, I think so.

Here is one error:
Update #6003
Failed: ALTER TABLE {views_view} ADD UNIQUE KEY name (name)

Notice that previous update already defines this key:
Update #6000
CREATE TABLE {views_view} ( `vid` INT unsigned NOT NULL auto_increment, `name` VARCHAR(32) NOT NULL DEFAULT '', `description` VARCHAR(255) DEFAULT '', `tag` VARCHAR(255) DEFAULT '', `view_php` BLOB DEFAULT NULL, `base_table` VARCHAR(64) NOT NULL DEFAULT '', `is_cacheable` TINYINT DEFAULT 0, PRIMARY KEY (vid), UNIQUE KEY name (name) ) /*!40100 DEFAULT CHARACTER SET UTF8 */

Here is another error:
Update #6006
Failed: CREATE TABLE {cache_views_data} ( `cid` VARCHAR(255) NOT NULL DEFAULT '', `data` LONGBLOB DEFAULT NULL, `expire` INT NOT NULL DEFAULT 0, `created` INT NOT NULL DEFAULT 0, `headers` TEXT DEFAULT NULL, `serialized` SMALLINT NOT NULL DEFAULT 1, PRIMARY KEY (cid), INDEX expire (expire) ) /*!40100 DEFAULT CHARACTER SET UTF8 */

Notice that it was already created here:
Update #6000
CREATE TABLE {cache_views_data} ( `cid` VARCHAR(255) NOT NULL DEFAULT '', `data` LONGBLOB DEFAULT NULL, `expire` INT NOT NULL DEFAULT 0, `created` INT NOT NULL DEFAULT 0, `headers` TEXT DEFAULT NULL, `serialized` SMALLINT NOT NULL DEFAULT 1, PRIMARY KEY (cid), INDEX expire (expire) ) /*!40100 DEFAULT CHARACTER SET UTF8 */

jweowu’s picture

Version: 6.x-2.6 » 6.x-2.8
StatusFileSize
new7.11 KB

I've updated my last patch to account for the changes added in 6.x-2.8.

O_o and bricestacey: Please test this patch, and set to RTBC if it looks good to you! I don't think this is likely to get committed otherwise.

eriktoyra’s picture

Status: Needs review » Reviewed & tested by the community

@jweowu: I've tested the patch and it works fine for me.

tbm13’s picture

I ran into the same issue when attempting a D5 to D6 upgrade. The patch works for me too.

tbm13’s picture

At least two users have now confirmed that this patch solves the problem for them. I'm not a Drupal developer so can someone please tell me what needs to happen now for this patch to be accepted?

jweowu’s picture

In general, the module maintainer(s) will commit a patch if they personally agree that it is a good patch, and it has been reviewed and tested by the community. A maintainer is far more likely to look at a patch in the first place if it is already RTBC, but they still need to find the time to do so in amongst all the other issues on their plate.

So hopefully merlinofchaos finds some time to have a look at this before the next release. I doubt that there's anything more to do in the meantime.

merlinofchaos’s picture

Thanks for the patience, jweowu. I glanced at the patch but I don't have a lot of time for it right now. I've been pretty full of things to do the last few months...so the Views patch queue has suffered a lot waiting for me to review it. This is very interesting, though, and seems likely to be the right direction.

merlinofchaos’s picture

Status: Reviewed & tested by the community » Needs review

Ok, this patch changes 'unique keys' to 'unique key' but the schema API documentation says it is 'unique keys'. What's going on here?

jweowu’s picture

I reverted views_schema_6000() (previously views_schema_1()) back to its original state (including any errors) and made all the subsequently-committed fixes and changes to the schema in the views_schema_6xxx() functions.

views_schema_6003() (and views_update_6003()) fixed this particular error:

function views_schema_6003() {
  $schema = views_schema(__FUNCTION__);
  $schema['views_view']['unique keys'] = array('name' => array('name'));
  unset($schema['views_view']['unique key']);
  return $schema;
}
function views_update_6003() {
   $ret = array();
   db_add_unique_key($ret, 'views_view', 'name', array('name'));
   return $ret;
}

This prevents the following error when updating from Drupal 5 (which applies all views_update_N()s to views_schema_6000 specifically)

Update 6003:
user warning: Duplicate key name 'name' query: ALTER TABLE views_view ADD UNIQUE KEY name (name) in [...]/includes/database.mysql-common.inc on line 403.

For fresh installations, calling views_schema() returns the final version of the schema, with all views_schema_6xxx() fixes applied in sequence (as per comments #5 and #7).

merlinofchaos’s picture

Ahh, interesting. Okay. Can we please add comments where the errors are so that other people looking at this can be pointed to where the errors are fixed? That will help prevent the confusion I just had. Otherwise I am 100% sure that someone will spot the error and submit a patch to fix it. =)

jweowu’s picture

StatusFileSize
new7.94 KB

Additional comments added :)

jweowu’s picture

StatusFileSize
new7.95 KB

New version because I missed a word in one of the comments, and I can't edit the previous attachment now.

merlinofchaos’s picture

Version: 6.x-2.8 » 7.x-3.x-dev
Status: Needs review » Patch (to be ported)

Committed to both 6.x branches -- this *almost* applies to 7.x (and 7.x appears to include a fix included here) so hopefully this one will be easy to port forward.

jweowu’s picture

StatusFileSize
new922 bytes

Excellent.

I'll try to have a look at the 7.x branch some time. I've not spent much time with 7.x, but it sounds like it should be straightforward.

It looks like there's an issue with the 6.x-3.x branch, however, as that contains a new views_update_6008() (committed to 3.x in #593668: Ability to change display ids) which needs to be dealt with.

Here's a patch for that.

jweowu’s picture

Version: 7.x-3.x-dev » 6.x-3.x-dev
Status: Patch (to be ported) » Needs review
dawehner’s picture

I personally suggest to add another issue.... This helps for example the people, who are porting patches to d7.

jweowu’s picture

I'm not sure whether you mean a new issue for this 6.x-3.x patch (which will also be relevant to the 7.x-3.x version), or a new issue for the 7.x port?

A single issue made sense to me, but I don't mind if it's split, so long as they're clearly marked as related. I'll leave it to someone else to create the new issue, though.

dawehner’s picture

I'm not sure whether you mean a new issue for this 6.x-3.x patch (which will also be relevant to the 7.x-3.x version), or a new issue for the 7.x port?

Look at the other issues. The patch was ported in the same issue as the original patch, i should know this :p

jweowu’s picture

Which patch was ported? (Did you miss part of your reply?). I think I may be losing something in the translation, sorry :/

I'm pretty sure you're saying that the new issue should be for the new 6.x-3.x patch, but FWIW I did have a reason for putting that here.

Given the extra hook_update_N() in 3.x, my preference would have been to commit the patch from #23 only to the 6.x-2.x branch, then port it to 6.x-3.x, and then port that to 7.x-3.x. That's why I reverted the version back to 6.x-3.x in #25/26, so that we could follow that sequence, and it seemed sensible to do it all in the one issue.

If you're thinking of fixing 7.x-3.x first and then back-porting to 6.x-3.x, then I can see why what I did looks a bit backwards, but given that 6.x-2.x and 6.x-3.x are virtually identical as far as this file is concerned, it seemed easier to port the patch forwards.

I am also wondering whether the numbering scheme is going to cause issues between the 2.x and 3.x branches? Currently we have a views_update_6008() which is only in 3.x, so what happens the next time there's an update for 2.x? Will that also be numbered 6008? Or if it applies to both branches, will it be 6008 in 2.x and 6009 in 3.x? Or do we skip 6008 in 2.x, and try to keep the numbers synchronised across both branches?

The hook_update_N docs indicate that updates for 6.x-3.x should be numbered 63xx. If updates that need to be added to both branches could end up out of sync anyhow, should we look at using the more explicit 62xx and 63xx numbering?

dawehner’s picture

No patch was ported. Thats the reason why there should be a new issue

jweowu’s picture

Well I'm back to being unsure about precisely what you are saying. Please go ahead and create the new issue according to your requirements, and I'll be happy to follow it up. Make sure you link to it in this issue so I can find it, though.

merlinofchaos’s picture

Version: 6.x-3.x-dev » 7.x-3.x-dev
Status: Needs review » Patch (to be ported)

jweowu: Because this patch was committed to 6.x but not 7.x, we need to use this issue to make sure it can get into 7.x properly. That's why dereine suggests creating a new issue. In general, it is always best to follow up a patch with a new issue.

Everything you put in #25 should be in a new issue, subtracting any comments about 7.x. You can then post in THIS issue to reference the new issue so we can follow the discussion properly.

Reverting this issue.

merlinofchaos’s picture

Ok, I've got to do another thing in the .install file so I have integrated the patch in #25.

merlinofchaos’s picture

I integrated update 6008 into both 2 and 3.

jweowu’s picture

Status: Patch (to be ported) » Needs review
StatusFileSize
new8.83 KB

Thanks for the clarification, and here's a patch for 7.x-3.x

I haven't tested this. I compared the 7.x-3.x views.install with the 6.x-3.x version in both the pre-patch and post-patch states, though. The only code changes between the two were changing $GLOBALS['db_type'] to db_driver(), and while ($block = db_fetch_object($result)) to foreach ($result as $block)

I also changed the "Implementation of hook_" wording to "Implements hook_", as that appeared to be the standard in Views 7.x (although I couldn't see any mention of this elsewhere in Drupal land... it that just a local convention?)

Once this is committed, a 7.x-3.x patch for #466250: Enlarge views_display.display_options can be made.

dawehner’s picture

Status: Needs review » Needs work

I had to remove drupal_install_schema: http://drupal.org/node/751340#comment-2775902

So this patch does not apply anymore

jweowu’s picture

Status: Needs work » Needs review
StatusFileSize
new8.65 KB

Patch updated

dawehner’s picture

Do you have an idea how i can test this code?

jweowu’s picture

I'm not too familiar with Drupal 7, so hopefully I'm not missing anything here, but it looks as if upgrading from previous versions of Drupal is not yet a concern in this version (the schema versions are still synchronised between 6.x and 7.x), so I think the main question is: Does views_schema() return the same array that it did pre-patch?

This could be compared and verified manually without very much effort (the output should be equivalent, although some of the children may end up in a different order, so you could use a recursive ksort before diffing the output). Alternatively, rename the functions, load both files, and check that old_views_schema() == new_views_schema() -- PHP doesn't care which order the elements are in unless you use ===.

dawehner’s picture

Status: Needs review » Fixed

Thanks.

Status: Fixed » Closed (fixed)

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