Skip to content
24 changes: 24 additions & 0 deletions tests/WP_SQLite_Translator_Tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,30 @@ public static function regexpOperators() {
);
}

public function testRegexpReplace() {
$this->assertQuery(
"INSERT INTO _options (option_name, option_value) VALUES ('test-ignore', '1');"
);
$this->assertQuery(
"INSERT INTO _options (option_name, option_value) VALUES ('test-remove', '2');"
);

$this->assertQuery( "SELECT * FROM _options WHERE REGEXP_REPLACE(option_name, '(-ignore|-remove)', '') = 'test'" );
$this->assertCount( 2, $this->engine->get_query_results() );

$this->assertQuery( "SELECT REGEXP_REPLACE( null, 'a', 'x') as result" );
$results = $this->engine->get_query_results();
$this->assertEquals( null, $results[0]->result );

$this->assertQuery( "SELECT REGEXP_REPLACE( 'abc', null, 'x') as result" );
$results = $this->engine->get_query_results();
$this->assertEquals( null, $results[0]->result );

$this->assertQuery( "SELECT REGEXP_REPLACE( 'abc', 'a', null) as result" );
$results = $this->engine->get_query_results();
$this->assertEquals( null, $results[0]->result );
}

public function testInsertDateNow() {
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('first', now());"
Expand Down
44 changes: 44 additions & 0 deletions wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public function __construct( $pdo ) {
'isnull' => 'isnull',
'if' => '_if',
'regexp' => 'regexp',
'regexp_replace' => 'regexp_replace',
'field' => 'field',
'log' => 'log',
'least' => 'least',
Expand Down Expand Up @@ -493,6 +494,49 @@ public function regexp( $pattern, $field ) {
return preg_match( $pattern, $field );
}

/**
* Method to emulate MySQL REGEXP_REPLACE() function.
*
* @param string|array $pattern Regular expression to search for (or array of strings).
* @param string|array $replacement The string or an array with strings to replace.
* @param string|array $field Haystack.
*
* @return Array if the field parameter is an array, or a string otherwise.
*/
public function regexp_replace( $field, $pattern, $replacement ) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I just checked and in MySQL REGEXP_REPLACE() also takes three optional parameters:

pos: The position in expr at which to start the search. If omitted, the default is 1.
occurrence: Which occurrence of a match to replace. If omitted, the default is 0 (which means “replace all occurrences”).
match_type: A string that specifies how to perform matching. The meaning is as described for REGEXP_LIKE().

Would you be up for adding a support for those? If not, that's fine, but let's at add them to the function signature and fail with an informative warning (REGEXP_REPLACE() don't support non-default values for $pos (fourth argument), .... if you need it then you can contribute here: ....) if they're set to non-default values.

Copy link
Author

Choose a reason for hiding this comment

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

Would you be up for adding a support for those?

I will try to do that!

/*
* If the original query says REGEXP BINARY
* the comparison is byte-by-byte and letter casing now
* matters since lower- and upper-case letters have different
* byte codes.
*
* The REGEXP function can't be easily made to accept two
* parameters, so we'll have to use a hack to get around this.
*
* If the first character of the pattern is a null byte, we'll
* remove it and make the comparison case-sensitive. This should
* be reasonably safe since PHP does not allow null bytes in
* regular expressions anyway.
*/
Comment on lines +507 to +520
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does regexp_replace support the BINARY keyword? I couldn't find anything. If it doesn't, let's remove this comment and the special casing for the null byte.

Copy link
Author

Choose a reason for hiding this comment

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

Isn't the binary-mode something global?
See: https://mariadb.com/docs/server/ref/mdb/cli/mariadb/binary-mode/


/* Return null if one of the required parameter is null */
if ( is_null( $field ) || is_null( $pattern ) || is_null( $replacement ) ) {
return null;
}

if ( "\x00" === $pattern[0] ) {
$pattern = substr( $pattern, 1 );
$flags = '';
} else {
// Otherwise, the search is case-insensitive.
$flags = 'i';
}
$pattern = str_replace( '/', '\/', $pattern );
$pattern = '/' . $pattern . '/' . $flags;

return preg_replace( $pattern, $replacement, $field );
}

/**
* Method to emulate MySQL FIELD() function.
*
Expand Down