I get the following error while running cron through drush:

WD cron: PDOException: SQLSTATE[22003]: Numeric value out of range: 1690 BIGINT UNSIGNED value is out of range in '("winak_beta"."subscriptions_queue"."last_sent" + "winak_beta"."subscriptions_queue"."send_interval")': SELECT [error]
* FROM {subscriptions_queue} WHERE suspended = 0 AND last_sent + send_interval < :time ORDER BY sqid LIMIT 0, 1; Array
(
    [:time] => 1392023661
)
 in _subscriptions_mail_cron() (line 48 of /var/www/vhost/winak/beta/sites/all/modules/subscriptions/subscriptions_mail.cron.inc).

I'm guessing the value of

last_sent + send_interval

is out of range but not quite sure how. Will investigate how to fix this temporarily.

Comments

Randomaniac’s picture

I fixed this by changing the

send_interval

to a 32 signed integer field in the database, as it was populated with 0 values. Strange enough, having a 32 unsigned integer field did not suffy.

I'm curious as to where these negative values came from, and whether others have experienced these as well?

We have recently updated to PHP 5.5. Is there a time function you use that behaves differently there?

salvis’s picture

Issue tags: -PDOException, -cron, -bigint

Well, you can define the send_intervals yourself through the UI. Did you define one with a negative value?

kkalashnikov’s picture

I am also facing same problem. The send interval is as "soon as possible(-1)".

So please provide me solution as soon as possible.

Pol’s picture

We're having the same problem at work.

Looking for a solution.

Pol’s picture

The solution is:

ALTER TABLE subscriptions_queue MODIFY send_interval INT(32) unsigned;

I will probably provide a patch soon.

salvis’s picture

Status: Active » Postponed (maintainer needs more info)

I don't understand where your negative intervals are coming from.

I see no indication on admin/config/system/subscriptions/intervals that entering negative seconds would do anything useful...

Messing with the database schema is NOT the solution.

glass.dimly’s picture

I'm not sure why it is presumed that this value can never be -1.

In the code, in subscriptions.admin.inc I see the following on ~790


function _subscriptions_user_settings_form_submit(array $form, array &$form_state) {
  $uid = subscriptions_arg(1, 'uid');
  if (isset($form_state['values']['reset']) && $form_state['values']['op'] == $form_state['values']['reset']) {
    if ($uid > 0) {
      db_update('subscriptions_user')
        ->fields(array(
          'digest' => -1,
          'secure_links' => -1,
          'send_interval' => -1,  // <-- here, value of send_interval is set to -1
 

Plus, the default value of this field in the SQL structure is -1.

glass.dimly’s picture

The problem here, I believe, is a call to subscriptions_write that simply passes along the -1 from the subscriptions_user table. I ended up doing the following:

    subscriptions_write($access_key = 'taxa', $module = 'node', $field = 'tid', $tid, $author_uid = -1, $uid, abs((int) $send_interval), $send_updates, $send_comments);

See abs((int) $send_interval. This means that send interval will never by negative.

This is caused by the user in question not having turned on their subscriptions, which are disabled by default.

But this doesn't fix the underlying problem. What needs to happen is that you need to manually set send_updates to 1 and send_interval to 0 or higher before you call write_subscription.

To fix this for an array of uids, you'd do something like this:

    $uids = ['my_array_of_uids']; // CHANGEME
    db_update('subscriptions_user')
      ->fields(array('send_updates' => 1))
      ->condition('uid', $uids, 'IN')
      ->execute();
    db_update('subscriptions_user')
      ->fields(array('send_interval' => 0))
      ->condition('uid', $uids, 'IN')
      ->condition('send_interval', 0, '<')
      ->execute();

Here's how you might fix this in the db:

function my_module_update_7001() {
  // Remove improper -1 send_interval values in subscriptions_queue.
  // See https://www.drupal.org/project/subscriptions/issues/2192739
  db_update('subscriptions_queue')
    ->fields(array('send_interval' => 0))
    ->condition('send_interval', 0, '<')
    ->execute();

  // Remove -1 send_interval values in subscriptions_user.
  db_update('subscriptions_user')
    ->fields(array('send_interval' => 0))
    ->condition('send_interval', 0, '<')
    ->execute();

  // Fix borked subscriptions.
  db_update('subscriptions')
    ->fields(array('send_interval' => 1))
    ->condition('send_interval', 0, '<')
    ->execute();
}

Honestly, I think subscriptions module should create a failsafe, logging to the database, saying something like "A subscription has been attempted for a user whose subscriptions are disabled. Refusing to add." It really depends on how you see this function: whether it is a helper function for internal use only, or an external API-like function. If it is to remain an internal function (which is sort of how it acts) then it could be renamed to _subscriptions_write. Another possible fix is simply to add a note like this: "Note: this function does not enable subscriptions for a user, and does not alter the subscriptions_user table."

I think that about covers it. Time for a stiff drink.

shaktik’s picture

@pol,

ALTER TABLE subscriptions_queue MODIFY send_interval varchar(32);

provide a patch soon.

salvis’s picture

Thank you for reminding me of my own design in #7, glass.dimly!

The -1 values are used to mean that the user wants to use the site defaults, and they are indeed default until the user changes them.

subscriptions.install defines 'send_interval' as 'int', which translates to MySQL INT according to
https://api.drupal.org/api/drupal/includes%21database%21schema.inc/group...
which is 4 byte signed, giving a range of -2147483648 to 2147483647

2147483647 should definitely be able to hold
1392023661

However the error message in the OP mentions "BIGINT" — what database are you using? Does adding a signed int and an unsigned int (last_sent) make the result a BIGINT? But even if it does, I don't see why comparing it to 1392023661 should be a problem...

#8 and #9 are NOT the right solutions.

salvis’s picture

Hmm, we never got to the bottom of this, and it seems to be a rare issue.

If anyone is still interested — what database are you using?