diff --git a/src/content/journal-entries/2024-11-19.md b/src/content/journal-entries/2024-11-19.md new file mode 100644 index 0000000..264ad06 --- /dev/null +++ b/src/content/journal-entries/2024-11-19.md @@ -0,0 +1,32 @@ +--- +title: MySQL JSON Shenanigans +date: 2024-11-19 +--- + +In an effort to support out-of-date installations of our app, I had to keep a JSON column in our database. The column is obsolete, as are the values within it; but these installations continue to use it. So, knowing this, I decided to put the proper values into the column. I didn't want to pollute the code of our services to do so, though. So I made it into a `GENERATED` column. + +I ran into two issues. + +First, MySQL doesn't have a way to omit `NULL` values from a JSON array. + +Second, the strings in the resulting array had `\u0000` interspersed between each character. This is due to how MySQL represents strings in a regular column versus how they are represented in a JSON column. I'd have to look it up, but I think I recall that by default MySQL varchars are 16-bits per character, and JSON strings are UTF-8. + +I "solved" the first issue by using `IF()` statements to represent all possible combinations of values. Luckily there were only 4. The only other solution I saw involved `TRIGGER`s. No, thank you. + +The second issue was solved by using `JSON_QUOTE()` followed by `JSON_UNQUOTE()` to remove the `\u0000` characters. + +```sql +ALTER TABLE lectures +MODIFY COLUMN vimeo_video_links JSON GENERATED ALWAYS AS ( + IF(m3u8_url IS NOT NULL AND mp4_url IS NOT NULL, + JSON_ARRAY(JSON_UNQUOTE(JSON_QUOTE(m3u8_url)), JSON_UNQUOTE(JSON_QUOTE(mp4_url))), + IF(m3u8_url IS NOT NULL AND mp4_url IS NULL, + JSON_ARRAY(JSON_UNQUOTE(JSON_QUOTE(m3u8_url))), + IF(m3u8_url IS NULL AND mp4_url IS NOT NULL, + JSON_ARRAY(JSON_UNQUOTE(JSON_QUOTE(mp4_url))), + NULL + ) + ) + ) +) STORED; +```