Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Почему то упорно не работает UDF [D6, FB1.5]


S@shka ©   (2004-09-15 02:59:00) 

function GetNextHour (var CurrentHour : TDateTime) : PChar; cdecl; export
const
onehour = 1/24;
var
t : TDateTime;
temp : String;
begin
 t := CurrentHour + oneHour;
 temp := FormatDateTime ('dd.mm.yyyy hh',t);
 temp := temp + ':00:20';
 temp := FormatDateTime ('dd.mm.yy hh:nn:ss',CurrentHour);
 Result := malloc (length(temp) + 1);
 StrPCopy (Result,temp);
end;

и InterBase описана как
DECLARE EXTERNAL FUNCTION F_NEXTHOUR
   TIMESTAMP
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'GetNextHour' MODULE_NAME 'as.dll'

на любой запрос вида
select f_nexthour ('15.09.2004 01:00:01') from RDB$database
получаем
30.12.1899 01:00:20

Не понимаю - что не так???


S@shka   (2004-09-15 14:49:00) [1]

Большое спасибо.


Digitman   (2004-09-15 14:13:00) [2]


> S@shka ©   (15.09.04 13:22) [8]


ФБ свежих релизов позволяет в запросах группировки по результатам, возвращаемым из UDF

так что для твоей задачи лучше было бы возвращать из UDF значение часа в этом дне (см. ф-цию DecodeTime)

тогда в запросе можно будет использовать

... GROUP BY GetTimestampHour(SomeIBTimeStampValue)


Digitman   (2004-09-15 14:02:00) [3]


> я же так понимаю при возвращении результата как TIMESTAMP
> необходимо выделять память так как передавать надо по ссылке


нет, выделять память в случаях, когда размер параметра совпадает с размером результата, совершенно необязательно

дело в том, что при передаче факт.параметра ИБ формирует временную его копию в своей памяти и передает в UDF ссылку на него

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

function GetNextHour (var IBDateTime : TISC_QUAD) : PISC_QUAD; cdecl;
 function ProcessInputParameter(dt: TDateTime): TDateTime;
 begin
   ... //здесь формируешь рез-т привычным образом и по нужному алгоритму
 end;
begin
Result := @IBDateTime; //результат передаем по ссылке на область памяти, занятую вх.параметром
Result^ := DateToQuad(ProcessInputParameter(QuadToDate(IBDateTime)));
end;

DECLARE EXTERNAL FUNCTION F_NEXTHOUR
  TIMESTAMP /* параметр по дифолту передается по ссылке */
RETURNS TIMESTAMP /* результат по дифолту так же возвращается по ссылке */
ENTRY_POINT 'GetNextHour' MODULE_NAME 'as.dll'


S@shka   (2004-09-15 13:22:00) [4]

Yes
именно в TimeStamp результат и нужен
я же так понимаю при возвращении результата как TIMESTAMP
необходимо выделять память так как передавать надо по ссылке
а как правильно это слелать я пока не нашел.
А вообще зачем это все нужно (может это проще можно сделать и не нужно никаких UDF брать)
Имеем табличку
Param             Time                 Value
 1              12.05.2004 11:00:01     1
 1              12.05.2004 11:01:01     1
 1              12.05.2004 11:02:11     1
 1              12.05.2004 11:03:36     1
 1              12.05.2004 12:00:01     1

И мне нужно определить, например, сумму значений
по каждому часу т.е.
time between 11:00 12:00 и т.д.
то есть для данного набора должен был выдать
 1 12.05.2004 12:00:00 4
 1 12.05.2004 13:00:00 1


Digitman   (2004-09-15 13:08:00) [5]


> S@shka ©   (15.09.04 12:50) [6]


мне не оч понятно, зачем результат возвращать в виде строки ...
чем оправдано это требование ? почему не вернуть рез-т в виде того же TISC_QUAD (timestamp) ? а потому ж при реальной необходимости форматнуть этот рез-т в строку, представляющую дату/время ? ведь если параметр типа TISC_QUAD и рез-т того же типа, то  это позволит обойтись без выделения памяти под рез-т !


S@shka   (2004-09-15 12:50:00) [6]

Да проблема то вообщем сформулирована была
нужно выполнить следующее округление до ровных часов вперед
Т.е.
Input  = '15.09.2004 01:25:05'
Output = '15.09.2004 02:00:00';
а с UDF или нет все равно,
мне казалось что в UDF будет проще реализовать данную задачу


Виталий Панасенко   (2004-09-15 11:52:00) [7]

А current_timestamp никак прикрутить нельзя и без UDF обойтись? Или я не совсем понял проблему ?


Digitman   (2004-09-15 11:34:00) [8]

uses
 IBHeader

const

MSecsPerDay10 = MSecsPerDay * 10; // миллисекунд в сутках * 10
IBDateDelta = 15018; // разница в днях между датами Delphi и IBDatabase

//внутренняя ф-ция для преобразования даты/времени из формата IB в формат Делфи
function QuadToDate(ibd: TISC_QUAD): TDateTime;
begin
  Result:= ibd.gds_quad_high - IBDateDelta + ibd.gds_quad_low / MSecsPerDay10;
end;

//внутренняя ф-ция для преобразования даты/времени из формата Делфи в формат IB
function DateToQuad(d: TDateTime): TISC_QUAD;
var
  Days: Integer;
begin
  Days:= Trunc(d);
  Result.gds_quad_high:= Days + IBDateDelta;
  Result.gds_quad_low:= Trunc((d - Days) * MSecsPerDay10);
end;

function GetNextHour (var IBDateTime : TISC_QUAD) : PChar; cdecl;
...
var
DelphiDate : TDateTime;
...
begin
DelphiDateTime := QuadToDate(IBDateTime);
....
end;


S@shka   (2004-09-15 10:39:00) [9]

А как же время то передавать ???
Мне нужно в UDF передать TDateTime
и вернуть из него TDateTime + один час с округлением
до ровных часов назад
Т.е.
Input  = '15.09.2004 01:25:05'
Output = '15.09.2004 02:00:00';


Digitman   (2004-09-15 08:29:00) [10]


> S@shka ©   (15.09.04 02:59)  


см. [1]

IB-совместимые системы используют совершенно иной формат представления даты/времени

кр.того, malloc() нежелательно (а вскоре и недопустимо будет) использовать хотя бы по соображениям кроссплатформенности ... для аллокации памяти под возвращаемый рез-т следует использовать ib_util_malloc() в составе поставляемой штатно в дистрибутиве системы библ-ки ib_utils.dll


Fay   (2004-09-15 04:18:00) [11]

Иди на ibase.ru. Найдёшь там инфу о написании UDF.
Обратишь внимание, что
1) IB/FB не знают, что есть TDateTime
2) Использование тобой переменной типа String ничем не оправдано.


Наверх

Титульная страница Поиск, карта сайта Написать письмо