ユーザー定義関数で日付時刻やBLOBを扱う
アナハイムテクノロジー
はやしつとむ
2009/7/21
Firebirdでの日付時刻型の扱い
Firebirdの内部における日付時刻型は、そのままではCやDelphiで利用することができません。そのため、以下のAPIを利用してFirebirdから渡された日付時刻を変換し、また、戻り値として渡さなくてはなりません。
●isc_decode_sql_date():
Firebirdの内部日付形式をCの日付構造体に変換する
●isc_encode_sql_date():
Cの日付構造体をFirebirdの内部日付形式に変換する
●isc_decode_sql_time():
Firebird内部時刻形式をCの時刻構造体に変換する
●isc_encode_sql_time():
Cの時刻構造体をFirebirdの内部時刻形式に変換する
●isc_decode_timestamp():
Firebirdの内部タイムスタンプ形式をCのタイムスタンプ構造体に変換する(従来はisc_decode_date()でした。これは、下位互換性のために残されています)
●isc_encode_timestamp():
Cのタイムスタンプ構造体をFirebirdの内部タイムスタンプ形式に変換する(従来はisc_encode_date()でした。これは、下位互換性のために残されています)
ib_udfライブラリには日付時刻型の関数は含まれていないので、fbudfライブラリのコードを見てみることにしましょう。
fbudf.cpp(517)
FBUDF_API ISC_TIMESTAMP* addYear(ISC_TIMESTAMP* v, const ISC_LONG& nyears)
{
tm times;
internal::decode_timestamp(v, ×);
times.tm_year += nyears;
internal::encode_timestamp(×, v);
return v;
}
まず、Cの時刻型であるtm型のtimesを宣言し、ISC_TIMESTAMP型で渡されてきたvをisc_decode_timestamp()関数でCの時刻型に変換しています。そして、tm型のメンバであるtm_yearにint型で渡されたnyearを加算しています。そのtimesをisc_encode_timestamp()関数を使って再びFirebirdのTimestamp型へ変換して戻しています。
では、Delphiで同じことをしてみます。
library UDF_sample2;
uses
SysUtils, Windows;
type
TM = record
tm_sec : integer; // Seconds
tm_min : integer; // Minutes
tm_hour : integer; // Hour (0--23)
tm_mday : integer; // Day of month (1--31)
tm_mon : integer; // Month (0--11)
tm_year : integer; // Year (calendar year minus 1900)
tm_wday : integer; // Weekday (0--6) Sunday = 0)
tm_yday : integer; // Day of year (0--365)
tm_isdst : integer; // 0 if daylight savings time is not in effect)
end;
PTM = ^TM;
Long = Longint;
ULong= Longword;
ISC_TIMESTAMP = record
timestamp_date : Long;
timestamp_time : ULong;
end;
PISC_TIMESTAMP = ^ISC_TIMESTAMP;
procedure isc_encode_timestamp
(tm_date: PTM; ib_date: PISC_TIMESTAMP);stdcall; external 'fbclient.dll';
procedure isc_decode_timestamp
(ib_date: PISC_TIMESTAMP;tm_date: PTM); stdcall; external 'fbclient.dll';
procedure isc_decode_sql_date
(var ib_date: Long;tm_date: PTM); stdcall; external 'fbclient.dll';
procedure isc_encode_sql_date
(tm_date: PTM; var ib_date: Long); stdcall; external 'fbclient.dll';
procedure isc_decode_sql_time
(var ib_date: ULong;tm_date: PTM); stdcall; external 'fbclient.dll';
procedure isc_encode_sql_time
(tm_date: PTM; var ib_date: ULong); stdcall; external 'fbclient.dll';
{$R *.res}
function tomneko_addYear(var v:ISC_TIMESTAMP; var nyears:Integer):PISC_TIMESTAMP;stdcall;
var
times:tm;
begin
isc_decode_timestamp(@v, @times);
times.tm_year := times.tm_year + nyears;
isc_encode_timestamp(@times, @v);
result := @v;
end;
exports
tomneko_addYear;
begin
end.
●登録用スクリプト:
DECLARE EXTERNAL FUNCTION TOMNEKO_ADDYEAR TIMESTAMP, INTEGER RETURNS TIMESTAMP ENTRY_POINT 'tomneko_addYear' MODULE_NAME 'UDF_sample2';
●使用例:
SQL> CREATE TABLE T_DATE (TM DATE);
SQL> INSERT INTO T_DATE VALUES ('2004/1/1');
SQL> SELECT TOMNEKO_ADDYEAR(TM, 2) FROM T_DATE;
TOMNEKO_ADDYEAR
=========================
2006-01-01 00:00:00.0000
Firebirdから渡されたvのアドレスを、そのままresultとしているところがミソで、戻り値用にtm型のメモリを確保しないようにしているわけです。
| 1/4 |
| Index | |
| ユーザー定義関数で日付時刻やBLOBを扱う | |
| Page 1 Firebirdでの日付時刻型の扱い |
|
| Page 2 EncodeDate関数 UDFでBLOBを扱う |
|
| Page 3 BLOB UDFのサンプル(1) BLOB UDFのサンプル(2) |
|
| Page 4 最後に |
|
| Yet another OSS DB:Firebird |
TechTargetジャパン
- やはりSELECT文は永遠のテーマです (2012/2/7)
Database Expertフォーラムの2012年1月のアクセスランキングをお届けします。定番の記事を一気に追い抜いてあの記事が…… - SELECT文で取り出したデータを加工して表示する (2012/1/25)
SELECT文で取り出したデータを対象に四則演算する方法など、データを見やすくする方法を解説します - 2012年は私たちが勉強会を盛り上げる! (2012/1/23)
2011年12月、データベース業界初の女子会が発足しました。そこで、女子会を盛り上げていってくれそうな2人にお話を伺いました - 複数の条件を指定してSELECT文を実行する (2012/1/13)
複数の条件を指定してSELECT文を実行する方法と、条件指定に必要な論理演算子、比較演算子の役割を解説します
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -
