Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
1-1106656531
Антоныч
2005-01-25 15:35
2005.02.06
Переместисть курсор в конец строки


4-1103014445
Виталий17
2004-12-14 11:54
2005.02.06
Проблема замены изображения кнопки "Пуск" в Windows 2000


1-1106391045
Леха
2005-01-22 13:50
2005.02.06
копия реестра


1-1106217787
Алексей
2005-01-20 13:43
2005.02.06
Поиск в Memo


3-1105254096
XAdmin
2005-01-09 10:01
2005.02.06
GetCurrentRecord(PChar), обратное преобразование





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский