数据库

本类阅读TOP10

·SQL语句导入导出大全
·SQL Server日期计算
·SQL语句导入导出大全
·SQL to Excel 的应用
·Oracle中password file的作用及说明
·MS SQLServer OLEDB分布式事务无法启动的一般解决方案
·sqlserver2000数据库置疑的解决方法
·一个比较实用的大数据量分页存储过程
·如何在正运行 SQL Server 7.0 的服务器之间传输登录和密码
·SQL中两台服务器间使用连接服务器

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
[UDF系列]如何编写InterBase UDF 之二

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

(接上一篇)

如何编写InterBase UDF

warton

怎么编写字符串和日期型处理函数的UDF呢?

 

下面编写一个“Left“函数

    内存分配问题:

              如果你使用IB(InterBase)5.1以下版本的话,在你的单元文件中键入下面的声明:

function malloc(Bytes: Integer): Pointer; cdecl; external 'msvcrt.dll';

       如果你有5.5以上的版本,你就不需要这么做了。这样,先确定ib_util.pas 文件在你的编译器可以找到的路径中,并且ib_util.dll也在你的搜索路径之中。

最简单的方法是放到的库可搜索到的路径。

                            c:\Program Files\InterBase Corp\InterBase\include

然后复制

              c:\Program Files\InterBase Corp\InterBase\lib\ib_util.dll

        到你的windows系统目录下(典型的是:c:\Windows\System)。最后在你的单元文件的use子句中将ib_util.pas加进去

                uses

               ...,

ib_util;

为什么有如此奇特的内存分配?为什么我不能用AllocMem分配内存,或者其它方法?问题很简单:你不能,所以不要问!更复杂的问题是每一个编译器使用它喜欢的算法来进行内存管理,这是被操作系统控制着的。例如,VC和Delphi管理内存的方式不同,猜这是为什么?IB是在VC下编译的,在5.5以前的版本中,你必须直接指定运行库。在IB5.5之后,IB给了一个IB调用使得这成为可能。既然这样,那我们继续进行编写字符串操作的函数。

 

构建函数

       在新的单元文件中,作如下声明:

function Left(sz: PChar; Cnt: Integer): PChar; cdecl; export;

    在函数实现部分:

               (* Return the Cnt leftmost characters of sz *)
function Left(sz: PChar; var Cnt: Integer): PChar;
var
  i: Integer;
begin
  if (sz = nil) then
    result := nil
  else begin
    i := 0;
    while ((sz[i] <> #0) and (i < cnt)) do Inc(i);
    result := ib_util_malloc(i+1);
    Move(sz[0], result[0], i);
    result[i] := #0;
  end;
end;

 

在你的工程文件中,在“exports“部分键入:

               exports
               Modulo,
               Left;
 

Now,再次编译工程项目….

现在,为了使用函数,在ISQL中重新连接数据库,输入:

                declare external function f_Left

               cstring(64), integer

               returns cstring(64) free_it

entry_point 'Left' module_name 'dll name minus ".dll"';

测试这个函...

select f_Left('Hello', 3) from rdb$database

 

仍然相当简单,哈?

 

上我们来编写一个时间函数

 

       IB6中,有三种不同的时期类型被支持,DATE,TIME,TIMESTAMP,与IB5.5及以前老版本中的相比,TIMESTAMP 的数据类型实质上相当于IB5.5DATE类型。

       为了在你的程序中”decode””encode”这些类型。你应该了解一点IB API相关的信息。输入以下代码:

interface
...
 
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;
 
  ISC_TIMESTAMP = record
    timestamp_date : Long;
    timestamp_time : ULong;
  end;
 
  PISC_TIMESTAMP = ^ISC_TIMESTAMP;
 
implementation
...
 
procedure isc_encode_timestamp  (tm_date: PTM;
                                                            ib_date: PISC_TIMESTAMP);
                                stdcall; external IBASE_DLL;
 
procedure isc_decode_timestamp  (ib_date: PISC_TIMESTAMP;
                                 tm_date: PTM);
                                stdcall; external IBASE_DLL;
 
 
procedure isc_decode_sql_date   (var ib_date: Long;
                                 tm_date: PTM);
                                stdcall; external IBASE_DLL;
 
procedure isc_encode_sql_date   (tm_date: PTM;
                                 var ib_date: Long);
                                stdcall; external IBASE_DLL;
 
 
 
procedure isc_decode_sql_time   (var ib_date: ULong;
                                 tm_date: PTM);
                                stdcall; external IBASE_DLL;
 
procedure isc_encode_sql_time   (tm_date: PTM;
                                 var ib_date: ULong);
                                stdcall; external IBASE_DLL;

现在我们写日期UDF:

       在单元文件的interface部分,输入声明:

function Year(var ib_date: Long): Integer; cdecl; export;
function Hour(var ib_time: ULong): Integer; cdecl; export;

implementation(实现)部分,输入:

function Year(var ib_date: Long): Integer;
var
  tm_date: TM;
begin
  isc_decode_sql_date(@ib_date, @tm_date);
  result := tm_date.tm_year + 1900;
end;
 
function Hour(var ib_time: ULong): Integer;
var
  tm_date: TM;
begin
  isc_decode_sql_time(@ib_time, @tm_date);
  result := tm_date.tm_hour;
end;

最好,在你的工程文件中:在““部分,输入:

exports

Modulo,

Left,

Year,

Hour;

现在编译工程...

 

为了使用这个函数,就像上面那样:用ISQL连接数据库,输入:

declare external function f_Year
date
returns integer by value
entry_point 'Year' module_name 'dll name minus ".dll"';
 
declare external function f_Hour
time
returns integer by value
entry_point 'Hour' module_name 'dll name minus ".dll"';

最后再测试一下看!

select f_Year(cast('7/11/00' as date)) from rdb$database

这一部分并非像前面字符串和整数那样操作哪样了,但是还是相当...simple,哼!

编写Linux/Unix平台的UDF

(未完待续!!)




相关文章

相关软件