[pgsql-jp: 41250] Re: ユーザー定義関数の作り方
Tomoaki Sato
sato @ sraoss.co.jp
2012年 10月 15日 (月) 22:59:10 JST
佐藤です。
> 山田です。具体策を示していただきありがとうございます。
> お陰さまで、整数配列の加算は上手く出来ました。
>
> とても便利なコマンドを紹介していただいたのですが、経験不足のため、
> src/backend/utils/adt/arrayfuncs.cなどを理解するのに時間がかかってお
> ります。
>
> ところで、
> resultをfloat8
> DatumGetInt32をDatumGetFlaot8
> PG_RETURN_INT32をPG_RETURN_Float8
> として、実数配列の加算を行ったところ、無意味に大きな整数を示します。
>
> そのまま、実数にも適用できるのでしょうか?
> ご教授いただければ幸いです。
データ型に応じた処理を行っていないのではないでしょうか。以下のようにデー
タ型に応じて処理を分ける必要があります。
switch (elmtyp)
{
case INT2OID:
result = Int16GetDatum(
DatumGetInt16(result) + DatumGetInt16(elemsp[i]));
break;
case INT4OID:
result = Int32GetDatum(
DatumGetInt32(result) + DatumGetInt32(elemsp[i]));
break;
試しに書いみたコードを添付しておきます。
# と書きましたが、ML に承認待ちになってしまったので、メールの最後にコー
# ドを貼りつけておきます。
> >>よく考えると、配列の要素を足すだけなら、C で関数を作らずに SQL、
> 将来、C言語に依存した関数を作りたいためです。御手数をおかけいたしま
> す。
>
> >>イテレーター
> STLのイテレーターのことでしょうか?
> 現時点で解決しなければならない課題ではありませんが、参照先などあれば
> 教えてもらえないでしょうか?
ヘッダファイル array.h 内の array_create_iterator、array_iterate 関数
のことです。
----------------------------- from here ------------------------------
#include "postgres.h"
#include "fmgr.h"
#include "utils/array.h"
#include "catalog/pg_type.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(sum_array);
Datum
sum_array(PG_FUNCTION_ARGS)
{
ArrayType *arg;
Oid elmtyp;
int16 elmlen;
bool elmbyval;
char elmalign;
Datum *elemsp;
bool *nullsp;
int nelemsp;
Datum result;
int i;
if (PG_ARGISNULL(0))
{
PG_RETURN_NULL();
}
arg = PG_GETARG_ARRAYTYPE_P(0);
elmtyp = ARR_ELEMTYPE(arg);
switch (elmtyp)
{
case INT2OID:
case INT4OID:
case INT8OID:
case FLOAT4OID:
case FLOAT8OID:
break;
default:
elog(ERROR, "could not determine data type of input");
break;
}
get_typlenbyvalalign(elmtyp, &elmlen, &elmbyval, &elmalign);
deconstruct_array(arg, elmtyp, elmlen, elmbyval, elmalign,
&elemsp, &nullsp, &nelemsp);
result = 0;
for (i = 0; i < nelemsp; i++)
{
if (nullsp[i])
{
elog(DEBUG1, "elemsp[%d]: NULL", i);
continue;
}
switch (elmtyp)
{
case INT2OID:
result = Int16GetDatum(
DatumGetInt16(result) + DatumGetInt16(elemsp[i]));
break;
case INT4OID:
result = Int32GetDatum(
DatumGetInt32(result) + DatumGetInt32(elemsp[i]));
break;
case INT8OID:
result = Int64GetDatum(
DatumGetInt64(result) + DatumGetInt64(elemsp[i]));
break;
case FLOAT4OID:
result = Float4GetDatum(
DatumGetFloat4(result) + DatumGetFloat4(elemsp[i]));
break;
case FLOAT8OID:
result = Float8GetDatum(
DatumGetFloat8(result) + DatumGetFloat8(elemsp[i]));
break;
default:
break;
}
}
pfree(elemsp);
pfree(nullsp);
PG_RETURN_DATUM(result);
}
------------------------------ to here -------------------------------
----
Tomoaki Sato <sato @ sraoss.co.jp>
SRA OSS, Inc. Japan
pgsql-jp メーリングリストの案内