Разбить оператор ORDER BY в массив - PullRequest
1 голос
/ 22 июня 2010

Я пытаюсь разбить оператор ORDER BY SQL-запроса на массив. Первый наклон:

order_by.split(',')

, но это не работает для порядка с помощью утверждений, подобных следующему:

SUBSTRING('test',1,3) ASC, SUBSTRING('test2', 2,2 ) DESC

Желаемый результат для вышеприведенного оператора будет:

["SUBSTRING('test',1,3) ASC", "SUBSTRING('test2', 2,2 ) DESC"]

Я вполне уверен, что это сработало бы, если бы я мог сопоставить любую запятую, которая не заключена в parethesis, но я не могу найти способ сделать это в регулярном выражении ruby, поскольку lookbehind не поддерживается.

Ответы [ 3 ]

1 голос
/ 22 июня 2010

Самым простым способом было бы сделать preg_replace_callback, чтобы заменить скобки на заполнитель, затем взорвать данные, затем перебрать и поставить скобки обратно.

0 голосов
/ 22 июня 2010

Как правило, вы не можете использовать регулярные выражения для синтаксического анализа нерегулярного языка.

Попробуйте использовать Rockit для создания реальной грамматики и синтаксического анализатора для необходимого вам подмножества SQL.

0 голосов
/ 22 июня 2010

Хотя я подозреваю, что, возможно, все еще есть способ сделать это с помощью регулярных выражений, вы также можете сделать это с помощью простого анализа строки.

Найдите все запятые в строке, а затем переходите вперед или назад от этой точки(не имеет значения, какие, если скобки сбалансированы правильно), добавив одну для открытой скобки и вычитая одну для закрытой скобки.Если у вас нет 0 в конце, вы находитесь внутри фигурной скобки, поэтому вам не нужна запятая.

Разделите все остальные запятые.

РЕДАКТИРОВАТЬ

Хотя комментарий о сбое этой методологии в случае скобок, заключенных в запятые, действителен, возможно, вы имеете дело с запросами, достаточно простыми, чтобы не беспокоиться об этом.Если это так, это должно работать:

def in_brackets(str,pos)
  cnt = 0
  str[pos,str.length].each_char do |c|
    if c == '('
      cnt += 1
    elsif c == ')'
      cnt -= 1
    end
  end

  return cnt != 0
end

def split_on_some_commas(str) 
  offset = -1
  split_pts = []

  while (offset = str.index(",",offset+1))
    if !in_brackets(str,offset)
      split_pts << offset
    end
  end

  split_pts << str.length

  pos = 0

  ret = []
  split_pts.each do |pt|
    ret << str[pos..(pt-1)].strip
    pos = pt+1
  end

  return ret
end

puts split_on_some_commas("SUBSTRING('test',1,3) ASC, SUBSTRING('test2', 2,2 ) DESC, SUBSTRING('test2', 2,2 ) DESC").inspect
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...