db_query(): Problems with variable substitution and LIKE

I was working on porting a module to D6 this morning. In the process of doing the port I wanted to clean up the UI a little bit so I converted some of the larger select elements to autocomplete. Here's a look at the autocomplete function:

function mymodule_data_autocomplete($string='') {
  $matches = array();
  if(strlen($string > 2) {
    $results = db_query('SELECT data FROM {mymodule_data} WHERE data LIKE "%%s%"',
$string);
    while($result = db_result($results)) {
      $matches[$result] = $result;
    } 
  }
  drupal_json($matches);
}

After setting up the menu callback I quickly noticed my autocomplete function wasn't filtering results. Regardless of what input it was given it cheerfully returned the entire list of available values from the database. I figured my query must be off so I dropped to a command line and tested it with mysql. Nope, works as advertised.

I spent a few minutes scratching my head then replaced the "%%s%" with "%' . $string . '%". This got the function to start filtering based on input...sort of. I was getting on average half the expected results back. After more head scratching and tinkering with the input field I realized that LIKE was doing case sensitive search without the BINARY keyword! WTF?

According to google this kind of behavior is a known issue.

Attempted fix #1: doubling up the %'s

   $results = db_query('SELECT data FROM {mymodule_data} WHERE data LIKE "%%s%%"',
$string);

No dice. Still getting every record in the database.

Attempted fix #2:mod the string

  $string = '%' . $string . '%';
  $results = db_query('SELECT data FROM {mymodule_data} WHERE data LIKE "%s"',
$string);

Bingo! For whatever reason bracketing a variable substitution (eg. %s, %d) with %'s breaks the variable substitution, but adding the %'s to the string works like a charm. Go figure.

Drupal Variable Substitution

$results = db_query('select data from {mymodule_data} where data like "%%s%"',
$string);

Might you have meant:

$results = db_query('select data from {mymodule_data} where data like "%%%s%%"',
$string);

Drupal's variable substitution in db_query makes % characters special. Doubling in each case you want a literal '%' solves the problem. I assume you want "%searchstring%" passed to the SQL query. %%%s%% should do it.

Submitted by brycem32 on Thu, 03/04/2010 - 16:50.
% double up %%

Actually I didn't try %%%s%% but I definitely will next time I find myself in a similar situation. Thanks for pointing this out.

Submitted by freeman on Fri, 03/05/2010 - 13:47.

Freeman on web stuff

If it's wrong, bad or
stupid, let me just say that
I am not surprised.

- author unknown

User login

Navigation

More Drupal hotness

Powered by Drupal, an open source content management system