Skip to content
/ server Public

MDEV-21181 Add Support for Generated Invisible Primary Keys#4718

Open
jaeheonshim wants to merge 1 commit intoMariaDB:mainfrom
jaeheonshim:MDEV-21181
Open

MDEV-21181 Add Support for Generated Invisible Primary Keys#4718
jaeheonshim wants to merge 1 commit intoMariaDB:mainfrom
jaeheonshim:MDEV-21181

Conversation

@jaeheonshim
Copy link

Jira: MDEV-21181

This PR implements a new session/global option sql_generate_invisible_primary_key. When this option is ON, MariaDB will automatically generate an invisible primary key for tables created without an explicit primary key.

The type of the auto-generated primary key is BIGINT UNSIGNED AUTO_INCREMENT. The primary key has the INVISIBLE_FULL attribute, meaning that to the user, it effectively does not exist and it is hidden from SHOW CREATE TABLE and SHOW COLUMNS. Furthermore, the user cannot explicitly drop the auto-generated primary key. However, if the user later adds their own primary key, the generated PK field and key are dropped.

Internally, the name of the generated primary key is _inv_PK, but this does not prevent the user from creating or adding their own column named _inv_PK. In that case, the generated primary key will be suffixed with a number (e.g. _inv_PK1, _inv_PK2, etc.).

@CLAassistant
Copy link

CLAassistant commented Mar 2, 2026

CLA assistant check
All committers have signed the CLA.

@gkodinov gkodinov added the External Contribution All PRs from entities outside of MariaDB Foundation, Corporation, Codership agreements. label Mar 2, 2026
Copy link
Member

@gkodinov gkodinov left a comment

Choose a reason for hiding this comment

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

Thank you for your contributions. This is a preliminary review.

Couple of things to fix:

  • please squash your changes into a single commit and add a commit message that follows CODING_STANDARDS.md
  • please make sure the tests are passing. There's one test to re-record and one to fix.

@jaeheonshim jaeheonshim force-pushed the MDEV-21181 branch 2 times, most recently from 829e2a2 to ebe9abd Compare March 3, 2026 05:06
@jaeheonshim jaeheonshim requested a review from gkodinov March 3, 2026 05:08
This PR implements a new session/global option
`sql_generate_invisible_primary_key`. When this option is on, MariaDB
will automatically generate an invisible primary key for tables created
without an explicit primary key. The type of the auto-generated primary
key is `BIGINT UNSIGNED AUTO_INCREMENT`. If an ALTER TABLE ADD PRIMARY
KEY statement is executed on a table with an generated primary key, the
generated primary key will be silently dropped.

Notes:
- Internally, the generated primary key has the INVISIBLE_FULL
  attribute. This means that the key and column effectively do not
  exist to the user and will not appear in SHOW CREATE TABLE and SHOW
  COLUMNS. Furthermore, the user cannot explicitly drop the
  generated primary key.
- The column name of the invisible generated primary key is _inv_PK.
  If the user creates their own column named _inv_PK, the generated
  primary key column's name will be suffixed with a number.
- If the storage engine does not support auto increment, no generated
  primary key will be added.
bitmap_clear_all(&table->tmp_set);
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
{
if (field->invisible == INVISIBLE_FULL)
Copy link
Member

Choose a reason for hiding this comment

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

I do not quite follow the whole logic here:

 if (field->invisible == INVISIBLE_FULL)
    {
      /*
        If the user added a pk of their own, and this was a generated pk field,
        we drop the generated pk field. Other wise, we want to carry it over to
        the new table.
      */
      if (should_replace_generated_pk && generated_pk_field == field)
      {
        continue;
      }
      if (generated_pk_field == field)
      {
        def= new (root) Create_field(thd, field, field);
        new_create_list.push_back(def, root);
      }
      continue;
    }

Please simplify!

I would do it as follows:

if (field->invisible == INVISIBLE_FULL)
{ 

  /*
        If the user added a pk of their own, and this was a generated pk field,
        we drop the generated pk field. Other wise, we want to carry it over to
        the new table.
  */
  if (generated_pk_field == field && !should_replace_generated_pk)
  {
    def= new (root) Create_field(thd, field, field);
    new_create_list.push_back(def, root);
  }
  continue;
}

return 0;
}

static bool is_auto_pk_field(Field *field)
Copy link
Member

Choose a reason for hiding this comment

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

I'd also check if the name. Not 100 fool-prof vs me doing:

CREATE TABLE t1 (_inv_PK SERIAL INVISIBLE PRIMARY KEY, c2 INT) ENGINE=InnoDB;

then the next ALTER TABLE dropping my manually defined primary key, i.e.

ALTER TABLE t1 ADD uniq_1 PRIMARY KEY;

But still better than nothing.

Please add a test case for this and have it documented in the MDEV that even explicitly created primary keys will be replaced in this case!

#
--source include/have_debug.inc

SET SESSION debug_dbug="+d,test_invisible_index,test_completely_invisible";
Copy link
Member

Choose a reason for hiding this comment

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

I'd also add a non-debug version of all this test: to explore the visible effects of the change. What is it btw?

The PR says "Innodb"! This is important for InnoDB afaik as it uses a clustered primary key to store data, so there's always a primary key of some sort. But Is it important for for the other storage engines?

Maybe it's best done inside InnoDB (as suggested by the MDEV)? Or still at server level, but only for InnoDB tables? Not sure. I guess, it'll have to wait for the final review this one.

But please document the visible effects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

External Contribution All PRs from entities outside of MariaDB Foundation, Corporation, Codership agreements.

Development

Successfully merging this pull request may close these issues.

3 participants