I have encountered this problem when I try to save big int value by drupal_write_record().

I have defined a field as unsigned big int in the schema, meaning in MySQL I can save value ranging from 0 to 4294967295.

In php, integer value is ranging from -2147483648 to 2147483647.

When I want to save a value like 3453966699, it actually belongs to float type but can be saved as unsigned int(10) not to mention bigint.

But in the drupal_write_record(), all int type including normal and big will be forced to cast to int type.

      if ($info['type'] == 'int' || $info['type'] == 'serial') {
        $fields[$field] = (int) $fields[$field];
      }

So (int) 3453966699 will become -841000597

Can we make it work with unsigned int and big int?

      if ($info['type'] == 'int' || $info['type'] == 'serial') {
        if ($info['unsigned'] || $info['size'] == 'big') {
          $fields[$field] = (float) $fields[$field];
        }
        else {
          $fields[$field] = (int) $fields[$field];
        }
      }

Note that this primarily affects Windows. For some reason even 64 bit PHP on 64 bit Windows is typecasting int to a 32 bit integer and not 64 - so we are treating it as a string to ensure we are putting in the right number, not a munged float or 2147483647

CommentFileSizeAuthor
#67 windows-failed-tests-67.jpg342.66 KBelusivemind
#64 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.64.patch938 byteselusivemind
#64 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.test-only.patch2 KBelusivemind
#61 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.60.patch937 byteselusivemind
#61 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.test-only.patch1.99 KBelusivemind
#54 merge-query-big-int.1947468.d8.54.test-only.patch5.58 KBelusivemind
#52 merge-query-big-int.1947468.d8.52.test-only.patch1.54 KBelusivemind
#46 drupal_8_no_problem.patch1.54 KBelusivemind
#40 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.40.patch2.91 KBelusivemind
#37 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.34.patch2.95 KBelusivemind
#34 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.34.patch2.91 KBelusivemind
#31 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.31.patch2.91 KBelusivemind
#27 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.27.patch2.89 KBelusivemind
#25 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.25.patch2.86 KBelusivemind
#23 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.23.patch2.81 KBelusivemind
#21 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.21.patch2.89 KBelusivemind
#18 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.18.patch2.84 KBelusivemind
#15 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.15.patch2.49 KBelusivemind
#12 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.12.patch2.42 KBelusivemind
#9 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.9.patch2.29 KBelusivemind
#6 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.6.patch2.27 KBelusivemind
#3 drupal-write-record-wrong-cast-type-bigint-unsigned.1947468.d7.patch778 byteselusivemind

Comments

ufku’s picture

Title: drupal_write_record() cast wrong type for unsigned int and big int value » drupal_write_record() cast wrong type for unsigned int and big int value (32-bit PHP)

I've experienced such issue on Win7(64bit) + PHP(32bit)

A workaround could be to change the field type to 'bigint' in schema definition.

However, there is no solution for very big integers on 32bit PHP. For instance 999999999999999999 will be treated as 1.0E+18 unless it is in string form.

ufku’s picture

Issue summary: View changes

Add example of data type convertion

elusivemind’s picture

Issue summary: View changes

The problem is bigger than this. Even on 64 bit Windows 10 and 64 bit PHP when you try to insert a bigint value larger than an int, it will only go to 2147483647 ... and value greater than that will stop there.

This is problematic for when I am trying to store values like Twitter tweet id's as a bigint(20) which is defineable by Drupal, but not assignable with drupal_write_record.

Working up a patch now.

elusivemind’s picture

Patch to correct incorrect typecasting error. Cannot be float as it will change all exponential values not in the number to zeroes.

elusivemind’s picture

Status: Active » Needs review

Status: Needs review » Needs work
elusivemind’s picture

elusivemind’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
elusivemind’s picture

elusivemind’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
elusivemind’s picture

Addressed testing errors

elusivemind’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
elusivemind’s picture

Addressed test case

elusivemind’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
elusivemind’s picture

elusivemind’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
elusivemind’s picture

Status: Needs work » Needs review
StatusFileSize
new2.89 KB

Status: Needs review » Needs work
elusivemind’s picture

Status: Needs work » Needs review
StatusFileSize
new2.81 KB

Status: Needs review » Needs work
elusivemind’s picture

Status: Needs work » Needs review
StatusFileSize
new2.86 KB

Status: Needs review » Needs work
elusivemind’s picture

Status: Needs work » Needs review
StatusFileSize
new2.89 KB

Perhaps using a reserved word in sql for the test case.

Status: Needs review » Needs work

Status: Needs work » Needs review

Status: Needs review » Needs work
elusivemind’s picture

Status: Needs work » Needs review
StatusFileSize
new2.91 KB
elusivemind’s picture

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

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

Wrong test case. Should be asserting against identical not true. Corrected

Status: Needs review » Needs work
elusivemind’s picture

elusivemind’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
elusivemind’s picture

Status: Needs work » Needs review
StatusFileSize
new2.91 KB

Added a better test assertion since it is returning the proper value but not testing with the correct test.

elusivemind’s picture

@cilefen -- It looks like this has passed the simpletest. Can I get some more input on this?

elusivemind’s picture

Issue tags: +Module review
elusivemind’s picture

Issue tags: -Module review
elusivemind’s picture

Issue summary: View changes
cilefen’s picture

@ElusiveMind Could you make a new comment with the existing patch and a test-only patch? Upload the test-only patch first so it will be tested first.

Are we sure this doesn't happen in Drupal 8?

elusivemind’s picture

StatusFileSize
new1.54 KB

I have confirmed that Drupal 8 does not have this issue. I have attached my schema addition and test to show that a bigint is properly handled in Drupal 8. This test passes out of the box. Do we need to include it in the Drupal 8 test suite?

Status: Needs review » Needs work

The last submitted patch, 46: drupal_8_no_problem.patch, failed testing.

elusivemind’s picture

that previous patch was not intended for testing against Drupal 7 ;)

elusivemind’s picture

Version: 7.x-dev » 8.0.x-dev
elusivemind’s picture

Status: Needs work » Needs review
elusivemind’s picture

Status: Needs review » Needs work

The last submitted patch, 52: merge-query-big-int.1947468.d8.52.test-only.patch, failed testing.

elusivemind’s picture

StatusFileSize
new5.58 KB

Including the InsertTest and proper default values for all elements where the schema was changed. Also ensured proper casting and comparisons in test methods.

elusivemind’s picture

Status: Needs work » Needs review
elusivemind’s picture

elusivemind’s picture

Ok - in Windows, it is converting to floats - which puts 0000 on the end of the number.

I located the typecasting code in:

https://api.drupal.org/api/drupal/core!includes!schema.inc/function/drup...

But changing that doesn't seem to fix the problem. Still digging, but any help as to where db_insert does it's data typing would be helpful. I've been looking for about 3 hours now.

cilefen’s picture

Issue tags: +MySQL
elusivemind’s picture

Version: 8.0.x-dev » 7.x-dev

The last submitted patch, 46: drupal_8_no_problem.patch, failed testing.

elusivemind’s picture

Status: Needs review » Needs work
elusivemind’s picture

Status: Needs work » Needs review

The last submitted patch, 54: merge-query-big-int.1947468.d8.54.test-only.patch, failed testing.

elusivemind’s picture

StatusFileSize
new342.66 KB

This test passed via the test bot, but in Windows, it fails. Please see the attached screen with the failed test on Windows. Same code.

elusivemind’s picture

After much gnashing of teeth, I think I am going to abandon this and consider drupal_write_record deprecated since it is not in Drupal 8 even though the code from it seems to be there but not doing much.

Using db_insert instead of drupal_write_records seems to resolve the issue present in Windows under Drupal 7. I will document this on the function's page.

elusivemind’s picture

tolstoydotcom’s picture

I have a custom entity to store tweets. Initially it was just storing the tweet ID as a string, but I updated it to also store the tweet ID as a bigint. On 32-bit Linux, the bigint version of tweet ID was being truncated to 2147483647. That's because my entity extends EntityAPIController, and EntityAPIController::save() uses drupal_write_record(). Applying the patch fixed that.

Since this affects those who call drupal_write_record() directly as well as those who have it called for them, it seems like this is something that would be good to fix on D7.

Status: Needs review » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.