Форум: "Базы";
Текущий архив: 2005.02.06;
Скачать: [xml.tar.bz2];
ВнизОшибка в 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;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.039 c