ユーザー定義関数で日付時刻や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」などを紹介していきます。今回は、「各種ガイドラインが示すコンプライアンス要件に、データベースのセキュリティはどのように記載されているのか」を解説します
|
|




