E
E
ertaquo2011-05-09 18:58:14
PHP
ertaquo, 2011-05-09 18:58:14

Regular expression replacement with partial string search?

There is a line with a request:

SELECT * FROM {table} WHERE name="123 {qwerty} 789" AND id IN (SELECT id FROM {other_table})

I would like to somehow replace "{table}" with "prefix_table". However
preg_replace('/\{([\w\d_]+)\}/', 'prefix_$1', $query);

will replace generally all curly braces, including "{qwerty}" in a string within a query. Is there any way to do the replacement without touching the rows? Maybe you can do a parity check or something else?
UPD:
Who cares about the solution, I did this:
function ReplaceTableNames($sql)
{
  $prefix = 'prefix_';

  $escape = false;
  $quot = false;
  $table = false;
  for ($i = 0; $i < strlen($sql); $i++)
  {
    switch($sql[$i])
    {
    case '\\':
      if ($quot !== false)
        $escape = !$escape;
      break;
    case '"':
    case '\'':
      if (!$escape)
      {
        if ($quot !== false)
        {
          if ($quot == $sql[$i])
          {
            $quot = false;
          }
        }
        else
        {
          $quot = $sql[$i];
          $table = false;
        }
      }
      else
      {
        $escape = false;
      }
      break;
    case '{':
      if ($quot === false)
      {
        $table = '';
      }
      break;
    case '}':
      if ($table !== false)
      {
        $sql = substr_replace($sql, $prefix.$table, $i - strlen($table) - 1, strlen($table) + 2);
        $i += strlen($prefix) - 1;
        $table = false;
      }
      break;
    default:
      if ($table !== false)
      {
        if (preg_match('|[\w\d_\.]+|i', $sql[$i]))
        {
          $table .= $sql[$i];
        }
        else
        {
          $table = false;
        }
      }
    }
  }

  return $sql;
}

The result is correct query string parsing, ignoring string character escaping and invalid table names.

Answer the question

In order to leave comments, you need to log in

6 answer(s)
S
Sergey, 2011-05-10
@seriyPS

In general, a very suspicious question. Are you sure you need it? It seems to me that no)
But even if you are sure, take a look for yourself. They offer you a regular expression, /(FROM|UPDATE|ALTER)\s+{([\w\d_]+)\}/iUand you give an example that breaks it UPDATE {table} SET `text`="пример запроса: SELECT * FROM {table}"... Despite the fact that queries that include data have not been used by normal people for 4 years already. There are also placeholders (at least PDO supports them in popup). Those. you will write , make all your wonderful replacements, and then use PDO to bind the data to the request. If this approach does not suit you, you need to think again carefully. If it doesn’t help, then make some more unique labels to highlight table names in the styleUPDATE {table} SET `text`=:text WHERE id IN( SELECT id FROM {other_table})
SELECT * FROM {#$table$#}. Well, an extreme case - write a full-fledged SQL parser according to any BNF rules. Although then most likely just wasting a lot of time.

A
adminimus, 2011-05-09
@adminimus

preg_replace('/\FROM\s+{([\w\d_]+)\}/i', 'FROM {prefix_$1}', $query);

what does not suit?

I
IDMan, 2011-05-09
@IDMan

preg_replace('/^(.*)\{([\w\d_]+)\}/iU', '$1 prefix_$2', $query);
We will only replace the first brackets. But I see you have "other_table" at the end of your query. Do you want to replace it too?

K
Kirill Dlussky, 2011-05-10
@Dlussky

If your current approach is very dear to you, then use `{table}` in queries, and in the data, escape the ` character through html-entity (and the rest of the quotes will not hurt). And if without perversions, then you were told above about placeholders in PDO.
PS I personally have my own bicycle, but there, again, tables are substituted along with the data, and there can be no arbitrary text in the request itself, I recommend that you reconsider your concept in this direction.

R
runcore, 2011-05-10
@runcore

if you just need to replace "{table}" with "prefix_table" then why are there regexps?

$query = str_replace('{table}','`prefix_table`',$query);

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question