Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.02.06;
Скачать: CL | DM;

Вниз

Ошибка в db.pas VCL Delphi. Метод TParams.ParseSQL   Найти похожие ветки 

 
kaif ©   (2005-01-03 15:42) [0]

реализован как-то небрежно.
При разборе текста SQL-запроса этот метод вызывается, если свойство ParamCheck компонента (например, IBQuery) равно True.
При этом символы кавычек, двойных кавычек и дурацких кавычек (`) называется Literals:

const
 Literals = ["""", """, "`"];

Функция

 function IsLiteral: Boolean;
 begin
   Result := CurChar in Literals;
 end;


проверяет, является ли текущий символ при разборе текста "литералом", и если является, то устанавливает флаг в стиле:

 if IsLiteral then Literal := Literal xor True;

То есть по сути переключает флаг туда-сюда, не сильно заморачиваясь на разбор "вложенных кавычек разных типов".
В результате мой запрос, содержащий нечетное число двойных кавычек, за которыми следует двоеточие, приводит в IBQuery к ошибке
XSQLDA index out of range.
Так как двоеточие в тексте воспринимает, как параметр.

И простой запрос вида:

SELECT * FROM AAA WHERE NAME LIKE "":"

приводит к сбою программы.

Кто с этим сталкивался и как лечил?
Может я что-то понимаю неверно и этот код должен работать... Но он явно работает неправильно (я имею в виду код в db.pas).


 
Sandman25 ©   (2005-01-03 15:47) [1]

kaif ©   (03.01.05 15:42)

Если использовать параметры вместо строковых константЮ, ошибка исчезнет. Вы, скорее всего, это знаете, в связи с чем возникает вопрос - зачем используются строковые параметры? Если пишется свой движок, то можно попытаться написать наследника TParams.


 
kaif ©   (2005-01-03 16:08) [2]

2 Sandman25 ©
Мне не всегда удобно использовать параметры. Тексты запросов "поиска по вхождению" у меня часто формируются на ходу в виде простых конструкций вида:

SELECT * FROM AAA WHERE
UPPER(NAME) LIKE "%ПРИНТЕР%" OR
UPPER(NAME) LIKE "%LEXMARK%" OR
UPPER(NAME) LIKE "%Z52%"

И я никак не ожидал такого подвоха от "улавливателя параметров" TParams.ParseSQL.
Неужели выход в том, чтобы "приспосабливаться" всякий раз к ошибкам VCL вместо того, чтобы их исправлять? Я вообще узнал об этой ошибке совершенно случайно - после того, как юзер набрал подряд кавычки и двоеточие в названии товара.
Уйти от этой ошибки мне проще, просто отключив ParamCheck. Ошибка вовсе не в том, что "нужно  все делать через параметры", в том, что нужно делать "либо через параметры", либо "отключив параметры вообще", так как параметры "вылавливаются" разборщиком параметров в файле db.pas как-то небрежно.


 
Sandman25 ©   (2005-01-03 16:50) [3]

[2] kaif ©   (03.01.05 16:08)

Вы же сами всё прекрасно понимаете. Есть сравнительно мало вариантов:
1) SELECT * FROM AAA WHERE
UPPER(NAME) LIKE :name_printer OR
UPPER(NAME) LIKE :name_lexmark OR
UPPER(NAME) LIKE :name_z52
2) ParamCheck false, и полностью отказаться от параметров, используя AnsiQuotedStr, ShortDateFormat и прочее.
3) Переписать что-нибудь, что приводит к вызову ошибочного кода, заменив на вызов правильного кода.
Если первые два варианта не устраивают (судя по ответу), остается только последний.
Кстати, у нас на старой работе возникли аналогичные проблемы (правда, не в Delphi), решение было организационное - запрет пользователям использовать двойные кавычки в названии. Имеющиеся двойные кавычки были заменены на одинарные программно.


 
kaif ©   (2005-01-04 15:47) [4]

2 Sandman25 ©   (03.01.05 16:50) [3]
 Пожалуй Вы правы. Вариантов не так уж и много. Я попробую исправить db.pas. Я все же считаю это ошибкой: имеется "открывающая" одинарная кавычка, и, не дождавшись "закрывающей" одинарной, разборщик берет "двойную кавычку" и считает ее "закрывающей ту первую одинарную". ИМХО, это как-то неаккуратненько.


 
msguns ©   (2005-01-04 16:13) [5]

Я пошел по другому пути. Вместо того, чтобы парсить запрос, выуживая из него значения и тип полей (параметров), я созал свою коллекцию дескрипторов полей таблицы, где, в частности, есть поля, определяющие тип, значение, шаблон и т.д. аргумента поиска. В результате для получения запроса я просто "пробегаю" эту коллекцию, строя динамически его текст. Это несколько кривовато и громоздко в коде, зато абсолютно универсально и работает на любых стандартах SQL. Правда вот создать такие компоненты (на базе TDataSet) не удосужился. Наверно потому, что тямы маловато ;((


 
Sandman25 ©   (2005-01-04 16:13) [6]

[4] kaif ©   (04.01.05 15:47)

ИМХО, это как-то неаккуратненько.

Мягко говоря.
Удачи!


 
kaif ©   (2005-01-04 17:37) [7]

В рамках моей программы (Allegro) я исправил db.pas следующим образом: "при разборе текста запроса на предмет выявления параметров кавычками, обрамляющими явные строки, считать только простые одинарные кавычки":

То есть вместо
const
Literals = ["""", """, "`"];


Я записал
const
Literals = [""""];


Дело в том, что еще одну ошибку db.pas (не работает Refresh полей InternalCalc) мне уже пришлось править, так что измененный текст db.pas стал "частью проекта".

ИМХО, вполне можно отказаться от анализа любых кавычек, кроме простых, в части разбора TParams.ParseSQL, где вылавливаются параметры. По крайней мере, в моем случае (IBX + Firebird).

Всем спасибо. Если есть возражения против такого решения (подводные камни) - говорите. Я пока не вижу.



Страницы: 1 вся ветка

Текущий архив: 2005.02.06;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.488 c
1-1106489931
saNat
2005-01-23 17:18
2005.02.06
Пишу свой класс. Прошу рекомендации, замечания


1-1106408303
kyn66
2005-01-22 18:38
2005.02.06
Как установить EasyTable 6.03 D6


1-1106063571
Жуков
2005-01-18 18:52
2005.02.06
Добавление строки в переменную...


3-1104828890
yaric
2005-01-04 11:54
2005.02.06
Как проверить что две таблицы одинаковы


1-1106215977
Руслана
2005-01-20 13:12
2005.02.06
Как вызвать свою программу из трея?