I have created a custom services API method that changes node status from 0 to 1. When this method is called in Drupal 7.39 installation, I see the following error: "Integrity constraint violation: ... Column 'tid' cannot be null'". It looks as if taxonomy_node_update() is trying to save taxonomy id's for this node before the node itself has finished saving.

I have implemented a workaround by setting the value of 'taxonomy_maintain_index_table' to FALSE temporarily in hook_node_presave() when the status is being changed from 0 to 1 and setting it back to TRUE if any other change is being made.

However, this doesn't seem like a good solution since taxonomy_maintain_index_table is used in multiple places in Drupal core.

Any ideas of how I can work around this issue?

I don't see it happening with any other types of node updates or with other versions of Drupal core.

Thanks in advance!

Comments

nevets’s picture

What does your code look like? Without it, it is hard to comment on.

Alexey T’s picture

This is the implementation of hook_node_presave():

function mymodule_node_presave($node) {
// If status is being changed from 0 to 1, prevent taxonomy_node_update() from executing to avoid integrity constraint error
// Otherwise, enable it back
$loaded_node = node_load($node->nid);
if ($loaded_node) {
if (!$loaded_node->status && $node->status) {
variable_set('taxonomy_maintain_index_table', FALSE);
}
else {
variable_set('taxonomy_maintain_index_table', TRUE);
}
}
}

The code that sets node status to 1 looks as follows:

...

$old_node = node_load($nid);

// Check is given user has permission to update the node. If yes, do the following:

// Saving updated fields...

foreach ($node as $field => $value) {
$old_node->$field = $value;
}

node_save($old_node);

...

Thank you!

nevets’s picture

Where does the second chunk of code exist? What is the function it is part of? (I suspect you should not be calling node_save() and should be updating $node)

Alexey T’s picture

The second chunk of code exists in a submodule of services contrib module. In the implementation of hook_services_resources(), a new node API method is added. It is a custom function and not an implementation of any hook. The function first checks that the user whose account name is provided is authorized to update a node, and, if yes, updates the node. It calls node_save() instead of going directly to the database, because this is the standard Drupal way of updating a node. Is there anything wrong with that?

$node is just an array of data that is passed to the API method, whereas $old_node is obtained using node_load(), so it contains the actual node being updated.

drm’s picture

Why are you looping through every field in $node if you just want to set the status?

Alexey T’s picture

I am looping through every field because this same function can be used to update any node field whose value is provided in the $node array.

The API method is used on multiple Drupal 7 sites and has not caused any problems, except when changing the status from 0 to 1 on Drupal 7.39.

When I comment out these lines in taxonomy_node_update() core function:

taxonomy_delete_node_index($node);
taxonomy_build_node_index($node);

everything is back to normal.

Is there anything I can do to prevent taxonomy_node_update() hook from firing in certain cases (like when only the status is changed from 0 to 1), without setting “taxonomy_maintain_index_table” to FALSE? It is the attempt to update taxonomy indices while the node is being updated that seems to be causing the integrity constraint violation.