Add REVERSE() to user defined functions#434
Conversation
|
Thank you @teizz ! |
## Release `3.0.0-rc.6` Version bump and changelog update for release `3.0.0-rc.6`. **Changelog draft:** * Don't take a write lock for SET statements (fixes "database is locked" on connect) ([#443](#443)) * Add REVERSE() to user defined functions ([#434](#434)) * LALR(1) parser from official MySQL grammar ([#429](#429)) **Full changelog:** v3.0.0-rc.5...release/v3.0.0-rc.6 ## Next steps 1. **Review** the changes in this pull request. 2. **Push** any additional edits to this branch (`release/v3.0.0-rc.6`). 3. **Merge** this pull request to complete the release. Merging will automatically build the plugin ZIP and create a [GitHub release](https://github.com/WordPress/sqlite-database-integration/releases). > [!NOTE] > This is a **pre-release**. It will not be deployed to [WordPress.org](https://wordpress.org/plugins/sqlite-database-integration/).
|
Hi @teizz, thanks for implementing this! One question: This implementation doesn't handle multibyte strings, so calling |
|
Hi @JanJakes! I had actually given that some thought. I couldn't tell if the the plugin that broke for me really needed anything more than byte reversal. I think it's only using it as some index speed optimization. I also wasn't sure to what extend MySQL would actually handle unicode (especially combining characters and other grapheme clusters) and if you're ideally want some sort of bug-for-bug compatibility. In any case, I did have a couple of "workarounds" to get full unicode reversal without needing additional PHP extensions and I guess there's two choices:
The first option is simply The second which is very elegant in my opinion, but does require PHP 8.4 or newer (since that includes PRCE 10.44) to not see a sequence of multiple characters with multiple code points as a single very long character. Both these functions don't break the plugin I need. Feel free to swap the |
|
Thanks, @teizz! Ah, there is no |
|
I was surprised there isn't a public function reverse($str) {
if (null === $str) {
return null;
}
if(preg_match('/[^\x00-\x7F]/', $str)) {
preg_match_all('/./u', $str, $matches);
return implode('', array_reverse($matches[0]));
}
return strrev($str);
}Not sure on the PR etiquette here. Would you prefer me opening another PR, or are you wanting to patch this in yourself? Either is fine with me :) |
As discussed with @JanJakes in pull request #434 I've gone ahead and added the code to support unicode characters while keeping behavior aligned with how mysql reverses a utf8mb4 unicode string, i.e. it correctly reverses multi-byte characters, but fails to preserve the correct order for grapheme clusters / combining characters. As a practical example: both this implementation and mysql's REVERSE() function will reverse '🧟 🧟♂️ 🧟♀️' to become '♀🧟 ️♂🧟 🧟' instead of '🧟♀️ 🧟♂️ 🧟'. I've also gone ahead and added a check to enable a fast path with `strrev()` in case all characters are normal ASCII, this improves both speed and prevents additional allocation for arrays. Finally, I checked to see that ``` php preg_match_all( '/./u', $str, $matches ); return implode( '', array_reverse( $matches[0] ) ); ``` is actually about twice as fast as ``` php $chars = preg_split( '//u', $str, -1, PREG_SPLIT_NO_EMPTY ); return implode( '', array_reverse( $chars ) ); ``` --------- Co-authored-by: Jan Jakeš <jan@jakes.pro>
I ran into an issue where a plugin is using the REVERSE() function to add the reverse of a string into the database. Since this isn't supported by SQLite it breaks the plugin. This fixes it for me.