Skip to content
/ server Public

MDEV-11339 Support UUID v4 generation#3143

Closed
StefanoPetrilli wants to merge 1 commit intoMariaDB:11.5from
StefanoPetrilli:11.5-MDEV-11339
Closed

MDEV-11339 Support UUID v4 generation#3143
StefanoPetrilli wants to merge 1 commit intoMariaDB:11.5from
StefanoPetrilli:11.5-MDEV-11339

Conversation

@StefanoPetrilli
Copy link
Contributor

@StefanoPetrilli StefanoPetrilli commented Mar 21, 2024

  • *The Jira issue number for this PR is: MDEV-11339

Description

UUIDv4 generates random UUIDs, which means they are not based on timestamps or other predictable data. If you require UUIDs that are not predictable or reveal any information about the time they were generated, UUIDv4 is a better choice.

Release Notes

UUIDv4(): returns a UUIDv4

How can this PR be tested?

This PR adds automatic tests to test the new function

Basing the PR against the correct MariaDB version

  • This is a new feature and the PR is based against the latest MariaDB development branch.
  • This is a bug fix and the PR is based against the earliest maintained branch in which the bug can be reproduced.

PR quality check

  • I checked the CODING_STANDARDS.md file and my PR conforms to this where appropriate.
  • For any trivial modifications to the PR, I am ok with the reviewer making the changes themselves.

Copy link
Member

@grooverdan grooverdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work.

Copy link
Member

@grooverdan grooverdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for address @abarkov 's review.

Just addressing the windows compile issue, and get ready for a 11.6 and will be ready.

Thanks for the contribution.

@StefanoPetrilli StefanoPetrilli force-pushed the 11.5-MDEV-11339 branch 2 times, most recently from 5350e4d to 67ce722 Compare March 27, 2024 09:48
@grooverdan
Copy link
Member

I see last push went from intXstore -> mi_intXstore and then didn't bigendian fail like this test failure - something I could watch out for other BE test fails.

Copy link
Contributor

@abarkov abarkov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Stefano.
Can you please squash the two commits (the code and the tests) into a single commit?

This is how we usually do in MariaDB: the change and the covering test go in a single commit.

Also, I'm seeing some code and CMake changes in the patch with tests. This is confusing why we need a second commit fixing something that was done just in a previous commit. It's better to have everything done properly right in the first commit.

Thanks.

Copy link
Contributor

@abarkov abarkov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patch looks very good. Thanks for addressing review suggestions!

@abarkov
Copy link
Contributor

abarkov commented Apr 5, 2024

Hello @StefanoPetrilli.

I'm preparing a branch with UUIDv4() for testing by our QA team.
While working on it I realized there was a wrong inheritance in MariaDB class hierarchy:
UUID() erroneously inherited some VARCHAR features from SYS_GUID(), which should not happen.

I reported this problem as:
https://jira.mariadb.org/browse/MDEV-33827 - UUID() returns a NULL-able result
which is now fixed in 11.5.

This is the patch:
9b02b7c

The class Item_func_uuid now derives from something else than Item_func_sys_guid.

Unfortunately, I had to duplicate these methods responsible for non-deterministic behavior:

 bool const_item() const;
 table_map used_tables() const;
 bool check_vcol_func_processor(void *arg);

But this change guarantees that the functions UUID(), UUIDv4(), and UUIDv7() soon, have exactly the same behavior with all other SQL expressions returning UUID, like table columns and CAST(expr AS UUID).

@abarkov
Copy link
Contributor

abarkov commented Apr 5, 2024

After fixing MDEV-33827, I cherry-picked your patch again.
Then pushed two patches on top of it: they are marked as "Fixup" and "Fixup 2" in their commit comments.

Please have a look into this branch:
https://github.com/MariaDB/server/commits/bb-11.5-bar-MDEV-11339/

"Fixup" addresses the things we came up during discussions with the team (Daniel Black and Sergey Golubchik):

  • We don't need the code from my_uuid_v4.c in the server (at least at this point). So it was moved to plugin/type_uuid/, into a new class UUIDv4.
  • A failure in my_random_bytes() should not raise an error. A warning with a fallback should be OK instead.

"Fixup 2" additionally introduces a template Item_func_uuid_vx, to share as much as possible code between UUID() and UUIDv4() and the coming soon UUIDv7().

Do you agree with these additional changes? Do you have any suggestions for further improvements?

Note, I'm going to squash the "Fixup" commit into your main commit, if you don't mind. It will remain with your authorship.

@StefanoPetrilli
Copy link
Contributor Author

Hello @abarkov,

My only comment is that falling back to UUIDv1 in case of entropy error might not be the most appropriate choice. If I try to generate a UUIDv4 I would rather get an error than a UUIDv1 because they have different properties and is not what I asked for.

What do you think?

@abarkov
Copy link
Contributor

abarkov commented Apr 5, 2024

Hi @StefanoPetrilli,

We discussed with Sergei again.
Although, we think that the likelihood of the situation with a my_random_bytes() failure is near to 0,
still we're feeling somewhat not comfortable about raising the error, which will rollback the entire current transaction.

What about another possible solution:

 static void construct(char *to)
  {
    if (my_random_bytes((uchar*) to, 16) != MY_AES_OK)
    {
      push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
                          ER_UNKNOWN_ERROR,
                          "Failed to generate a random value for UUIDv4");
      /*
        This is very unlikely situation when my_random_bytes() fails.
        Let's fallback to my_rnd().
      */
      for (i=0; i < 4; i++)
        int4store(&buf[i*4], my_rnd(&sql_rand)*0xFFFFFFFF);
    }
    /*
      We have random bytes at to[6] and to[8].
      Let's inject proper version and variant to make it good UUIDv4.
    */
    inject_version_and_variant(to);
  }

Note, sql_rand is a global seed declared in sql/mysqld.cc.
The above code will likely additionally need a mutex lock around the loop with my_rnd().
What do you think about this version otherwise?

@StefanoPetrilli
Copy link
Contributor Author

Hello @abarkov,

I agree that the probability of an error is close to zero and for this reason I think both versions would be acceptable but personally, I like your last version more.

@grooverdan
Copy link
Member

Thanks @StefanoPetrilli very much for the contribution and making the base.

I'm closing this now per MDEV the current version is bb-11.5-bar-MDEV-11339 and is undergoing testing for 11.6.

@grooverdan grooverdan closed this Apr 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants