ユーザー定義関数で日付時刻や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 |
- Oracleライセンス「SE2」検証 CPUスレッド数制限はどんな仕組みで制御されるのか (2017/7/26)
データベース管理システムの運用でトラブルが発生したらどうするか。DBサポートスペシャリストが現場目線の解決Tipsをお届けします。今回は、Oracle SE2の「CPUスレッド数制限」がどんな仕組みで行われるのかを検証します - ドメイン参加後、SQL Serverが起動しなくなった (2017/7/24)
本連載では、「SQL Server」で発生するトラブルを「どんな方法で」「どのように」解決していくか、正しい対処のためのノウハウを紹介します。今回は、「ドメイン参加後にSQL Serverが起動しなくなった場合の対処方法」を解説します - さらに高度なSQL実行計画の取得」のために理解しておくべきこと (2017/7/21)
日本オラクルのデータベーススペシャリストが「DBAがすぐ実践できる即効テクニック」を紹介する本連載。今回は「より高度なSQL実行計画を取得するために、理解しておいてほしいこと」を解説します - データベースセキュリティが「各種ガイドライン」に記載され始めている事実 (2017/7/20)
本連載では、「データベースセキュリティに必要な対策」を学び、DBMSでの「具体的な実装方法」や「Tips」などを紹介していきます。今回は、「各種ガイドラインが示すコンプライアンス要件に、データベースのセキュリティはどのように記載されているのか」を解説します
|
|