14. 14
CREATE OR REPLACE FUNCTION add3(i integer )
RETURNS integer
LANGUAGE sql
AS $function$
SELECT i + 3;
$function$
;
CREATE FUNCTION
postgres=# SELECT add3(5);
add3
------
8
(1 row)
関数定義
関数実行
SQL で作成する例
15. 15
pl/pgsql で作成する例
postgres=# CREATE OR REPLACE FUNCTION sigma(i integer )
RETURNS integer
LANGUAGE plpgsql
AS $function$
DECLARE
sigma integer := 0;
c integer := 1;
BEGIN
FOR c IN 1 .. i LOOP
sigma := sigma + c;
END LOOP;
RETURN sigma;
END;
$function$
;
CREATE FUNCTION
postgres=#
postgres=# SELECT sigma(10);
sigma
-------
55
(1 row)
関数定義
関数実行
22. 22
SELECT id, data, data + '2/3' AS add, data - '2/3' AS sub FROM test;
id | data | add | sub
----+------+-------+-------
1 | 2/3 | 4/3 | 0/1
2 | 3/7 | 23/21 | -5/21
3 | 1/5 | 13/15 | -7/15
(3 rows)
SELECT id, data, data * '2/3' AS mul, data / '2/3' AS div FROM test;
id | data | mul | div
----+------+------+------
1 | 2/3 | 4/9 | 1/1
2 | 3/7 | 2/7 | 9/14
3 | 1/5 | 2/15 | 3/10
(3 rows)
test=# SELECT * FROM test ORDER BY data;
id | data
----+------
3 | 1/5
2 | 3/7
1 | 2/3
(3 rows)
test=# SELECT max(data), min(data) FROM test ;
max | min
-----+-----
2/3 | 1/5
(1 row)
四則演算
並び替え=比較演算
集約演算
58. 58
SELECT id, data, data + '2/3' AS add, data - '2/3' AS sub FROM test;
id | data | add | sub
----+------+-------+-------
1 | 2/3 | 4/3 | 0/1
2 | 3/7 | 23/21 | -5/21
3 | 1/5 | 13/15 | -7/15
(3 rows)
SELECT id, data, data * '2/3' AS mul, data / '2/3' AS div FROM test;
id | data | mul | div
----+------+------+------
1 | 2/3 | 4/9 | 1/1
2 | 3/7 | 2/7 | 9/14
3 | 1/5 | 2/15 | 3/10
(3 rows)
test=# SELECT * FROM test ORDER BY data;
id | data
----+------
3 | 1/5
2 | 3/7
1 | 2/3
(3 rows)
test=# SELECT max(data), min(data) FROM test ;
max | min
-----+-----
2/3 | 1/5
(1 row)
四則演算
並び替え=比較演算
集約演算
(再掲)
64. 64
入出力定義(入力定義)
C 言語関数
PG_FUNCTION_INFO_V1(fraction_in);
Datum
fraction_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
int n, d;
Fraction *result;
/* TODO: more smart parse */
if (sscanf(str, "%d/%d", &n, &d) != 2)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("pg_fraction:invalid input syntax: "%s"",
str)));
/* range check */
if (d == 0) {
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("pg_fraction:division by zero: "%s"",
str)));
}
result = (Fraction* ) palloc(sizeof(Fraction));
reduce_fraction(&n, &d);
if ( abs(n) > 99999 || abs(d) > 99999 ) {
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("pg_fraction:: overflow error (max=99999) "%s"",
str)));
}
result->numerator = n;
result->denominator = d;
result->value = (double) n / (double) d;
PG_RETURN_POINTER(result);
}
SQL 定義
CREATE TYPE fraction;
CREATE FUNCTION fraction_in(cstring)
RETURNS fraction
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
CREATE FUNCTION fraction_out(fraction)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
CREATE TYPE fraction (
INTERNALLENGTH = 16,
INPUT = fraction_in,
OUTPUT = fraction_out,
STORAGE = plain
);
typedef struct st_fraction {
int numerator;
int denominator;
double value;
} fraction;
C 言語ヘッダ
65. 65
入出力定義(出力定義)
C 言語関数
PG_FUNCTION_INFO_V1(fraction_out);
Datum
fraction_out(PG_FUNCTION_ARGS)
{
Fraction *fraction= (Fraction*) PG_GETARG_POINTER(0);
char *result;
result = psprintf("%d/%d", fraction->numerator, fraction->denominator);
PG_RETURN_CSTRING(result);
}
SQL 定義
CREATE TYPE fraction;
CREATE FUNCTION fraction_in(cstring)
RETURNS fraction
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
CREATE FUNCTION fraction_out(fraction)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
CREATE TYPE fraction (
INTERNALLENGTH = 16,
INPUT = fraction_in,
OUTPUT = fraction_out,
STORAGE = plain
);
66. 66
算術演算の定義( + 演算子)
CREATE FUNCTION
CREATE OPERATOR
PG_FUNCTION_INFO_V1(fraction_add);
Datum fraction_add(PG_FUNCTION_ARGS);
Datum fraction_add(PG_FUNCTION_ARGS) {
Fraction *f1;
Fraction *f2;
Fraction *result;
int n, d;
f1 = (Fraction*) PG_GETARG_POINTER(0);
f2 = (Fraction*) PG_GETARG_POINTER(1);
add_fraction_internal(
f1->numerator,
f1->denominator,
f2->numerator,
f2->denominator,
&n,
&d);
result = (Fraction*) palloc(sizeof(Fraction));
result->numerator = n;
result->denominator = d;
result->value = (double) n / (double) d;
PG_RETURN_POINTER(result);
}
SQL 定義
--
-- 加算関数を定義する
--
CREATE FUNCTION fraction_add(fraction, fraction)
RETURNS fraction
AS 'MODULE_PATHNAME'
PARALLEL SAFE
LANGUAGE C IMMUTABLE STRICT;
--
-- + 演算子を定義する
--
CREATE OPERATOR + (
leftarg = fraction,
rightarg = fraction,
procedure = fraction_add,
commutator = +
);
C 言語関数
67. 67
比較演算の定義( = 演算子の例)
C 言語関数
PG_FUNCTION_INFO_V1(fraction_eq);
Datum fraction_eq(PG_FUNCTION_ARGS);
Datum
fraction_eq(PG_FUNCTION_ARGS)
{
Fraction* f1 = (Fraction*) PG_GETARG_POINTER(0);
Fraction* f2 = (Fraction*) PG_GETARG_POINTER(1);
double f1_v = f1->value;
double f2_v = f2->value;
PG_RETURN_BOOL(fraction_cmp_internal( f1_v, f2_v) == 0);
}
SQL 定義
--
-- eq 比較関数を定義する
--
CREATE FUNCTION fraction_eq(fraction, fraction)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
--
-- = 演算子を定義する
--
CREATE OPERATOR = (
leftarg = fraction,
rightarg = fraction,
procedure = fraction_eq,
commutator = =,
RESTRICT = eqsel
);
CREATE FUNCTION
CREATE OPERATOR
68. 68
集約の定義( MAX 関数の定義例)
C 言語関数
PG_FUNCTION_INFO_V1(fraction_max);
Datum fraction_max(PG_FUNCTION_ARGS);
Datum fraction_max(PG_FUNCTION_ARGS) {
Fraction* f_l = (Fraction*) PG_GETARG_POINTER(0);
Fraction* f_r = (Fraction*) PG_GETARG_POINTER(1);
if (f_l->value > f_r->value ) {
PG_RETURN_POINTER(f_l);
} else {
PG_RETURN_POINTER(f_r);
}
}
SQL 定義
ーー
-- fraction_max 関数を定義する
--
CREATE FUNCTION fraction_max(fraction, fraction)
RETURNS fraction
AS 'MODULE_PATHNAME'
PARALLEL SAFE
IMMUTABLE
LANGUAGE C STRICT
;
--
-- fraction_max を集約関数 MAX として定義する
--
CREATE AGGREGATE max (fraction)
(
sfunc = fraction_max,
combinefunc = fraction_max,
stype = fraction,
initcond = '-99999/1',
parallel = safe
);
CREATE FUNCTION
CREATE AGGREGATE
69. 69
インデックスを有効にする定義
C 言語関数/*
* 2 値ではなく 3 値を返すのがポイント
*/
static int
fraction_cmp_internal(double a, double b)
{
if (a < b)
return -1;
if (a > b)
return 1;
return 0;
}
/*
* B-tree インデックス比較用の関数
*/
Datum
fraction_cmp(PG_FUNCTION_ARGS)
{
Fraction* f1 = (Fraction*) PG_GETARG_POINTER(0);
Fraction* f2 = (Fraction*) PG_GETARG_POINTER(1);
double f1_v = f1->value;
double f2_v = f2->value;
PG_RETURN_INT32(fraction_cmp_internal( f1_v, f2_v));
}
SQL 定義
--
-- B-tree index support
--
CREATE FUNCTION fraction_cmp(fraction, fraction)
RETURNS integer
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- freaction operator class
CREATE OPERATOR CLASS fraction_ops
DEFAULT FOR TYPE fraction USING btree AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
OPERATOR 3 = ,
OPERATOR 4 >= ,
OPERATOR 5 > ,
FUNCTION 1 fraction_cmp(fraction,
fraction);
CREATE FUNCTION
CREATE OPERATOR CLASS