-
Есть вот функция такая: (D2007, FB2, dbExpress):
function TSQLDatabaseThread.SelectSQLA(const Q: String; const ParamNames,
ParamValues: array of Variant): TSQLDataSet;
var Command: String;
PNI, PNC: Integer;
function ParamType(const Param: Variant): Byte;
var basicType: TVarType;
begin
basicType := VarType(Param) and VarTypeMask;
case basicType of
varEmpty : Result := VT_EMPTY;
varNull : Result := VT_NULL;
varSmallInt : Result := VT_SMALLINT;
varInteger : Result := VT_INTEGER;
varSingle : Result := VT_SINGLE;
varDouble : Result := VT_DOUBLE;
varCurrency : Result := VT_CURRENCY;
varDate : Result := VT_DATE;
varBoolean : Result := VT_BOOL;
varVariant : Result := VT_VARIANT;
varUnknown : Result := VT_UNKNOWN;
varByte : Result := VT_BYTE;
varWord : Result := VT_WORD;
varLongWord : Result := VT_WORD;
varInt64 : Result := VT_INT64;
varStrArg : Result := VT_STRING;
varString : Result := VT_STRING;
varAny : Result := VT_ANY;
varTypeMask : Result := VT_TYPEMASK;
else Result := VT_UNKNOWN;
end;
end;
begin
Result := TSQLDataSet.Create(nil);
if Connection.Connected=False then begin
Connection.Connected := True;
end;
Result.SQLConnection := Connection;
Result.ParamCheck := (Length(ParamNames)<>0);
Result.CommandText := Q;
Command := Parse(Q, #32, 1);
Result.Params.Clear;
Result.Close;
if Length(ParamNames)<>0 then begin
PNC := Length(ParamNames)-1; for PNI := 0 to PNC do begin
case ParamType(ParamValues[PNI]) of
VT_UNKNOWN,
VT_NULL : Result.Params.CreateParam(ftUnknown, ParamNames[PNI], ptInputOutput);
VT_SMALLINT : Result.Params.CreateParam(ftSmallInt, ParamNames[PNI], ptInputOutput);
VT_INTEGER,
VT_SINGLE : Result.Params.CreateParam(ftInteger, ParamNames[PNI], ptInputOutput);
VT_DOUBLE : Result.Params.CreateParam(ftFloat, ParamNames[PNI], ptInputOutput);
VT_CURRENCY : Result.Params.CreateParam(ftCurrency, ParamNames[PNI], ptInputOutput);
VT_DATE : Result.Params.CreateParam(ftDate, ParamNames[PNI], ptInputOutput);
VT_BOOL : Result.Params.CreateParam(ftBoolean, ParamNames[PNI], ptInputOutput);
VT_VARIANT : Result.Params.CreateParam(ftVariant, ParamNames[PNI], ptInputOutput);
VT_BYTE : Result.Params.CreateParam(ftFloat, ParamNames[PNI], ptInputOutput);
VT_WORD,
VT_LWORD : Result.Params.CreateParam(ftWord, ParamNames[PNI], ptInputOutput);
VT_INT64 : Result.Params.CreateParam(ftInteger, ParamNames[PNI], ptInputOutput);
VT_STRARG,
VT_STRING : Result.Params.CreateParam(ftString, ParamNames[PNI], ptInputOutput);
VT_ANY : Result.Params.CreateParam(ftVarBytes, ParamNames[PNI], ptInputOutput);
VT_TYPEMASK : Result.Params.CreateParam(ftUnknown, ParamNames[PNI], ptInputOutput);
else
Result.Params.CreateParam(ftVariant, ParamNames[PNI],
ptUnknown);
end;
Result.Params.ParamByName(ParamNames[PNI]).AsString :=
String(ParamValues[PNI]);
end;
end;
if (Command='SELECT') then begin
Result.Open
end else begin
Result.ExecSQL();
FinalizeSQL(Result);
end;
end; Почему-то если параметрами подсунуть скажем ['uid', 3] то выполняется нормально и возвращает датасет. А вот если подсунуть скажем ['uname', 'какая_то_строка'], выдает "Incorrect values within SQLDA structure". ParamCheck := False не помогло. Где могут быть грабли?
-
Можно поинтересоваться, зачем все эти танцы нужны? И почему для ФБ используется дбЕкспресс?
-
Танцы... для универсализации, наверное. Мне удобнее написать один раз функцию, выполняющую все виды запросов, и потом приспособить ее под отдельные цели вида ExecSQL(Query) и SelectSQL(Query).
Используется dbExpress потому, что по вынужденным причинам пересел на Tiburon, в котором IB компоненты нещадно глючат (видимо, сырые), а это оказались единственные компоненты, которые работают. FIB и иже с ними покупать не хочу - пишу для себя - дорого...
-
> для универсализации, наверное. Мне удобнее написать один > раз функцию, выполняющую все виды запросов,
Это бесперспективное заблуждение...
А по сути: - приводи сам запрос, - дбЕкспресс весьма специфичен, попытки на его основе что-то "универсализировать" за рамками работы с MySQL, обречены на провал, - данное сообщение означает, что функция клиентской длл не смогла выделить и заполнить область параметров.
-
А что вы можете предложить "в рамках" решения данного вопроса? Я не хочу использовать специфичный софт и компоненты, я часто пишу OpenSource, и часто пишу в команде (всем не поставишь). Возвращаться на Delphi 7 не хочу.
-
Лично я бы не гнался за "универсализацией". В данном случае мы же заранее знаем вид запроса, а значит и количество и качество параметров... Для получения наборов данных - одни компоненты, для выполнения остальных запросов - другие. А вид запроса меняй наздоровье в рантайме. И параметры будут создаваться "на лету" неявно. Останется только их определить в цикле по элементам открытого массива.
-
> дбЕкспресс весьма специфичен, попытки на его основе что- > то "универсализировать" за рамками работы с MySQL, обречены > на провал,
весьма смелое утверждение, надо признать
> Мне удобнее написать один раз функцию, выполняющую все виды > запросов, и потом приспособить ее под отдельные цели вида > ExecSQL(Query) и SelectSQL(Query).
имхо, излишне
-
> весьма смелое утверждение, надо признать
Да, смелое, согласен. Если у кого-то будут подтвержденные противоположные мнения - с удовольствием выслушаю.
-
> Johnmen © (04.11.08 21:25) [7] > Если у кого-то будут подтвержденные противоположные мнения - с удовольствием выслушаю.
Не будет. Сколько народ не учи, что быстрее чем через API и ручное управление транзакциями ничего нет. Все равно не понимают: то труп BDE где-то выкопают, то dbExpress, то ODBC. Нет, конечно, я понимаю кодеров на M$VC, Java - им деваться некуда от этих прослоек, да и самому из 1C коннектиться через ODBC приходилось. Но если ты пишешь на Delphi, нахрена лезть то в эти дебри ? Тот же IBX, хоть он и кривой на всю голову, но при определенном привыкании к глюкам позволяет нормально писать.
-
> Тот же IBX, хоть он и кривой на всю голову, но при определенном > привыкании к глюкам позволяет нормально писать.
а вот dbx для IB вовсе не кривой и ни к каким глюкам привыкать не нужно или нужно стать любителем кошерных компонентов, чтоб хвастаться своим любимым, но страшным способом?
-
> FIB и иже с ними покупать не хочу - пишу для себя - дорого. > ..
Все же стоило бы поискать по нышпоркам, ИМХО - для IB/FB/YA человечество ничего лучшего не изобрело.
> кривой на всю голову
- это можно сказать обо всем, кроме фибов, что вы попытаетесь так или иначе приспособить под FB.
-
> - это можно сказать обо всем, кроме фибов, что вы попытаетесь так или иначе приспособить под FB.
Никто уже давно не пытается :)
У половины людей из FirebirdFoundation самописные библиотеки. В том числе и у Сергея Бузаджи. По последней скажу: не кошерно это использовать в потомке TDataSet (имеющем пять действий Select, Refresh, Insert, Update, Delete) две транзакции - это годится только для студенческих курсовых, потому как практика в некоторых случаях заставляет использовать пять транзакций с разными параметрами. Поэтому у большинства людей пяти-транзакционные библиотеки.
Я свою писал на базе IBX от Delphi7. Конечно, пришлось обработать напильником, в некоторых местах - резал болгаркой и "приваривал". :) Зато не страдал фигней, и в процессе создания ни разу не пытался в отладчике выловить багу в говнокоде, к коему я причисляю FIBPlus, несмотря на его стабильность. IBX тоже не страдает чистотой кода, непонятно вообще, как Borland/CodeGear/Embarcadero выпустили это в продажу на фоне кода самой VCL. Наверное, чтобы потребители прочувствовали разницу ? :)
-
> потому как практика в некоторых случаях заставляет использовать > пять транзакций с разными параметрами. Поэтому у большинства > людей пяти-транзакционные библиотеки.
Нет, я такого авангардизма не понимаю :))) Интересно было бы ознакомиться с каким-нибудь примером острой необходимости пятитранзакционного датасета, ибо даже моя извращенная фантазия вряд ли подобное сможет породить.
Обработанный напильником IBX - это агхиинтересно, конечно. Но до какой степени можно обрабатывать это "чудо" напильником, если там сама фундаментальная идеология уже на старте во многом проигрывает фибам? Может, просто лучше правильно юзать фибы? ;)
-
>GRAND © (05.11.08 17:20) [12] > Но до какой степени можно обрабатывать это "чудо" напильником, если там сама фундаментальная идеология уже на старте во многом проигрывает фибам? Может, просто лучше правильно юзать фибы? ;)
Филосфия IBX = Философия TDataSet = Философия FIBPlus, также = моя библиотека. Потому, как только так и не иначе, если Вы хотите увидеть Ваш набор данных в TDBGrid и проч. До какой степени ? - Наверное, пока камня на камне не останется :)
Фундаментально - философия IBX проигрывает: 1) В подключениях. У меня может быть более чем одна клиентская библиотека доступа, в том числе и к устаревшему InterBase, и Embedded Firebird, с помощью которой я подгружаю данные из "БазыУдаленогоФилиала" в "ЦентральнуюБазу", которая где-то-там... 2) В транзакциях наборов данных. По минимуму - две (что уже есть в FIBPlus), по правильному - пять.
> Интересно было бы ознакомиться с каким-нибудь примером острой необходимости пятитранзакционного датасета, ибо даже моя извращенная фантазия вряд ли подобное сможет породить.
Видимо, у Вас не по настоящему извращенная фантазия :) ----------------------- Кстати, камень в огород IBX и FIBPlus. Попробуете сделать INSERT в наборе данных, потом Post набора данных, а потом - Update этой же самой (только что вставленной) записи и ее же Post. А потом посмотрите, какая версия сохранится. :)
Вот и я говорю - пять транзакций....
-
> Филосфия IBX = Философия TDataSet = Философия FIBPlus, также > = моя библиотека
А что тогда есть философия чуть более высокого уровня - TTable? ;) Вот тут-то мы и приходим к кардинальному различию: в FIBPlus этого уродство отсутствует.
> Кстати, камень в огород IBX и FIBPlus. Попробуете сделать > INSERT в наборе данных, потом Post набора данных, а потом > - Update этой же самой (только что вставленной) записи и > ее же Post. А потом посмотрите, какая версия сохранится. > :)
Проверил: последняя (проапдейченная) версия. Как и должно быть. Собственно, я здесь проблем не вижу вот по какой причине: пять операций с датасетами (Select, Refresh, Insert, Update, Delete) прекрасно делятся на читающие и пишущие. Первые две работают в читающей транзакции, остальные три - в пишущей. Я не вижу чего-то непреодолимого, что может заставить Select и Refresh работать в разных транзакциях, а также Insert, Update и Delete. Более того, смысла я этом тоже не вижу ;)
|