When building a text search into a website I'm passing it through a PHP loop:
$queryList=explode(' ', $queryString);
foreach ($queryList as $queryParm) {
foreach ($fields as $key => $query) {
$whereStr.=($key == 0) ? " AND (ucase($query) LIKE ?" : " OR ucase($query) LIKE ?";
$db->parms[]="%$queryParm%";
if ($key+1 == count($fields)) $whereStr.=")";
}
}
This will separate the query's words and make each one a separate parameter. I'm building a regex to only allow alphanumeric plus spaces, but now the problem is I need the SQL to match this regex, for example if there's an item named "FakeCo's Unicorn Repellant #123" then searching "fakecos unicorn repellant 123" should yield the result, ignoring the fact that the "'" and the "#" exist. In fact due to the structure of the list "123 fakeco" should show the result too.
Is there a way to apply a regex to a DB2 statement?
This is being ran against DB2 for i (version 7.1)
Edit: attempted solution (insert this before PHP mentioned above), some characters caused issues & had to be removed, poor performance when it did run
$sqlNeedsEscape=array("?", "'");
$ignoreChars="'\"?~!@#$%^&*()-=+[]{}|<>,./\\";
$ignoreChars=str_split($ignoreChars);
$whereBefore='';
$whereAfter='';
foreach ($ignoreChars as &$ic) {
if (in_array($ic, $sqlNeedsEscape)) $ic="'$ic";
error_log($ic);
$whereBefore.="replace(";
$whereAfter.=",'$ic','')";
}
Then change the $whereStr.=
line to:
$whereStr.=($key == 0) ? " AND (ucase(trim($whereBefore $query $whereAfter)) LIKE ?" : " OR $whereBefore ucase(trim($query)) $whereAfter LIKE ?";
Effectively it was replace(replace(replace(query, '!', ''), '@', ''), '#', '') for each field, only wrap several more replaces around that. I quit chasing this idea when I saw the impact it had on performance. I will speak with our RPG devs about the UDF solution suggested by Buck Calabro. It sounds like the only "real" solution possible.