Skip to content

[mysql] Add Fallback to column scanning when column_names is empty for stored procedures#4197

Open
romeoneverdies wants to merge 4 commits intolaunchbadge:mainfrom
romeoneverdies:main
Open

[mysql] Add Fallback to column scanning when column_names is empty for stored procedures#4197
romeoneverdies wants to merge 4 commits intolaunchbadge:mainfrom
romeoneverdies:main

Conversation

@romeoneverdies
Copy link

@romeoneverdies romeoneverdies commented Mar 19, 2026

Problem
When executing a MySQL/MariaDB stored procedure with CALL, the MySqlRow.column_names map is often empty due to MySQL protocol limitations on procedure result sets. This causes row.try_get("column_name") to fail with ColumnNotFound, forcing users to use positional indexing (try_get(0), etc.) as a workaround.
See: #1742 (open since 2022)

Solution
Add a fallback in the ColumnIndex<MySqlRow> impl for &str:

  • First try the existing column_names map (unchanged fast path for normal queries)
  • On miss: scan row.columns by comparing col.name.as_ref() to the requested name
  • Return matching index if found, otherwise original ColumnNotFound error

This enables reliable named access after CALL procedures without changing any user code.

Trade-offs

  • Linear scan over columns (typically < 20 → negligible performance impact)
  • No caching (could be future improvement with OnceCell + Mutex)
  • Tested manually on simple stored procedures returning named columns

Related
Fixes #1530
Closes #1742
Similar reports in #2206, Stack Overflow, etc.

Happy to add integration tests, make it opt-in (feature flag), or adjust based on feedback.

Copy link
Collaborator

@abonander abonander left a comment

Choose a reason for hiding this comment

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

Add a fallback in the ColumnIndex impl for &str:

  • First try the existing column_names map (unchanged fast path for normal queries)
  • On miss: scan row.columns by comparing col.name.as_ref() to the requested name

This is only a half-fix. A MariaDB maintainer made the point that we should always use the actual resultset header as the source of truth for columns. Lots of different things can happen to change what columns come back from a query, especially in the case of SELECT *. Ultimately, the column set we get from COM_STMT_PREPARE_OK should be treated as purely informational.

The actual fix here is to just always populate the hashmap from the resultset.

Linear scan over columns (typically < 20 → negligible performance impact)

It doesn't need to happen here, but one of the refactors I've been thinking we should do is separate FromRow into two separate phases:

  1. resolution of column names to offsets, which happens once at the beginning of the resultset.
  2. when decoding rows, use the previously calculated offsets instead of looking up by column name.

This would eliminate the need to have any sort of lookup overhead when decoding resultsets, which should really improve performance for queries that return many rows.

@romeoneverdies
Copy link
Author

  1. true but this "bug" has been around for more than 4 years... it looks like neither teams have looked into this issue. or decided to pitch the ball to the other team , 2) point is explicitly what this patch aims to avoid. (that's just kicking the can down the road.) but i will look into changing the fallback to a more upstream point where i can populate column_names with a similar fallback so that it occurs only once not every time a column is looked up.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[MySQL] Can't get by column name when calling stored procedure [MariaDB 10.5] Fail to get row value by column name

2 participants