Databases 10 min read

How MySQL Expands the '*' in SELECT Statements: Source Code Analysis

This article explains how MySQL 8.0.32 expands the '*' in a SELECT statement into all table columns, detailing the lexical parsing, query preparation, and the functions Item_asterisk::itemize, Query_block::prepare, Query_block::setup_wild, and insert_fields through source‑code excerpts.

Aikesheng Open Source Community
Aikesheng Open Source Community
Aikesheng Open Source Community
How MySQL Expands the '*' in SELECT Statements: Source Code Analysis

In MySQL 8.0.32 the asterisk in select * from table is expanded by the server layer into a list of all columns of the referenced tables before the storage engine is asked to return data.

The expansion occurs in two stages: the lexical & syntax analysis stage, which records the presence of asterisks, and the query preparation stage, which replaces each asterisk with the actual column items.

1. Overall Introduction

When the server receives a SELECT statement containing select * , it records the asterisk during parsing and later expands it during query preparation, so the storage engine only needs to return the requested columns.

2. Source Code Analysis

2.1 Item_asterisk::itemize()

bool Item_asterisk::itemize(Parse_context *pc, Item **res) {
  ...
  pc->select->with_wild++;
  return false;
}

Each asterisk encountered increments pc->select->with_wild , a counter stored in the current Query_block object.

2.2 Query_block::prepare()

bool Query_block::prepare(THD *thd, mem_root_deque
*insert_field_list) {
  ...
  if (with_wild && setup_wild(thd)) return true;
  ...
}

If with_wild is greater than zero, the method calls setup_wild() to perform the actual expansion.

2.3 Query_block::setup_wild()

bool Query_block::setup_wild(THD *thd) {
  ...
  for (auto it = fields.begin(); with_wild > 0 && it != fields.end(); ++it) {
    Item *item = *it;
    if (item->hidden) continue;
    Item_field *item_field;
    if (item->type() == Item::FIELD_ITEM &&
        (item_field = down_cast
(item)) &&
        item_field->is_asterisk()) {
      // handle asterisk
      ...
      with_wild--;
    }
  }
  return false;
}

The function iterates over the SELECT field list, identifies asterisk items, and either replaces them with a constant (in certain EXISTS sub‑queries) or calls insert_fields() to expand them into real column items.

2.4 insert_fields()

bool insert_fields(THD *thd, Query_block *query_block, const char *db_name,
                       const char *table_name, mem_root_deque
*fields,
                       mem_root_deque
::iterator *it, bool any_privileges) {
  ...
  while (true) {
    tables = user_it.get_next();
    if (tables == nullptr) break;
    // permission checks
    if (!any_privileges && !(tables->grant.privilege & SELECT_ACL)) {
      if (check_grant_all_columns(thd, SELECT_ACL, &field_iterator))
        return true;
    }
    // iterate over each column of the table
    for (; !field_iterator.end_of_fields(); field_iterator.next()) {
      Item *item = field_iterator.create_item(thd);
      if (!found) {
        found = true;
        *it = item; // replace '*'
      } else {
        *it = fields->insert(*it + 1, item); // add subsequent columns
      }
    }
  }
  return false;
}

This routine walks each table referenced by the SELECT, checks the current user’s SELECT privileges, and creates an Item for every column, inserting them into the SELECT list in place of the asterisk.

3. Summary

The server iterates over the SELECT field list and detects asterisks.

For each asterisk it decides whether to replace it with a constant (in specific EXISTS sub‑queries) or to expand it.

When expanding, tables are processed in the order they appear in the query.

Permission checks ensure the user can read the required columns.

Each column is turned into an Item and added to the SELECT list, completing the expansion.

SQLMySQLselectSource CodeDatabase Internalsquery preparation
Aikesheng Open Source Community
Written by

Aikesheng Open Source Community

The Aikesheng Open Source Community provides stable, enterprise‑grade MySQL open‑source tools and services, releases a premium open‑source component each year (1024), and continuously operates and maintains them.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.