Skip to content

Escape backslashes in MySQL JSON path keys - #759

Merged
josevalim merged 1 commit into
elixir-ecto:masterfrom
ybai08:fix-mysql-json-key-backslash
Oct 17, 2026
Merged

josevalim merged 1 commit into
elixir-ecto:masterfrom
ybai08:fix-mysql-json-key-backslash

Conversation

@ybai08

@ybai08 ybai08 commented Oct 17, 2026

Copy link
Copy Markdown
Contributor

The MySQL adapter's escape_json_key/1 escaped keys for the SQL string literal but not for MySQL's JSON path syntax. So after MySQL unescapes the string literal, a backslash in a key reaches the JSON path parser as an escape character. With meta = %{"a\\b" => 1, "a\\nb" => 2, "a\nb" => 3, "a\\" => 4} on MySQL 8.4:

query before after
p.meta["a\\b"] nil 1
p.meta["a\\nb"] 3 (the value for the key that contains a newline) 2
p.meta["a\\"] error 1064 (invalid JSON path) 4

The fix escapes \ and " for the JSON path first, then applies escape_string/1 for the SQL literal. The output for keys containing " or ' is unchanged, so the existing assertions still pass. I also ran the generated path form directly against MariaDB 11, and it resolves the same keys there.

Checks run:

  • mix test: 707 passed (new assertions in the json_extract_path test in myxql_test.exs)
  • mix format --check-formatted: clean
  • ECTO_ADAPTER=myxql mix test against MySQL 8.4 (docker): the same 11 StorageTest failures with and without this change, because the mysql/mysqldump client binaries aren't installed locally. Nothing else fails.
  • Ran the three queries in the table above through TestRepo against MySQL 8.4, before and after the change.

Not run: the earthly CI matrix, and MySQL with NO_BACKSLASH_ESCAPES (the adapter's escape_string/1 already assumes backslash escapes are enabled).

json_extract_path keys were only escaped for the SQL string literal, so
a backslash in a key reached MySQL's JSON path parser as an escape
character. A key such as "a\\b" matched nothing, "a\\nb" matched the key
containing a newline, and a key ending in a backslash raised a syntax
error.

Escape backslashes and double quotes for the JSON path first, then
escape the result for the SQL string literal.
@josevalim
josevalim merged commit 32cbeba into elixir-ecto:master Oct 17, 2026
10 checks passed
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.

2 participants