Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9bae7e4

Browse files
committed
Add +(pg_lsn,numeric) and -(pg_lsn,numeric) operators.
By using these operators, the number of bytes can be added into andsubtracted from LSN.Bump catalog version.Author: Fujii MasaoReviewed-by: Kyotaro Horiguchi, Michael Paquier, Asif RehmanDiscussion:https://postgr.es/m/ed9f7f74-e996-67f8-554a-52ebd3779b3b@oss.nttdata.com
1 parent324435e commit9bae7e4

File tree

10 files changed

+296
-2
lines changed

10 files changed

+296
-2
lines changed

‎doc/src/sgml/datatype.sgml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4801,7 +4801,13 @@ SELECT * FROM pg_attribute
48014801
standard comparison operators, like <literal>=</literal> and
48024802
<literal>&gt;</literal>. Two LSNs can be subtracted using the
48034803
<literal>-</literal> operator; the result is the number of bytes separating
4804-
those write-ahead log locations.
4804+
those write-ahead log locations. Also the number of bytes can be
4805+
added into and subtracted from LSN using the
4806+
<literal>+(pg_lsn,numeric)</literal> and
4807+
<literal>-(pg_lsn,numeric)</literal> operators, respectively. Note that
4808+
the calculated LSN should be in the range of <type>pg_lsn</type> type,
4809+
i.e., between <literal>0/0</literal> and
4810+
<literal>FFFFFFFF/FFFFFFFF</literal>.
48054811
</para>
48064812
</sect1>
48074813

‎src/backend/utils/adt/numeric.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include"utils/guc.h"
4242
#include"utils/int8.h"
4343
#include"utils/numeric.h"
44+
#include"utils/pg_lsn.h"
4445
#include"utils/sortsupport.h"
4546

4647
/* ----------
@@ -472,6 +473,7 @@ static void apply_typmod(NumericVar *var, int32 typmod);
472473
staticboolnumericvar_to_int32(constNumericVar*var,int32*result);
473474
staticboolnumericvar_to_int64(constNumericVar*var,int64*result);
474475
staticvoidint64_to_numericvar(int64val,NumericVar*var);
476+
staticboolnumericvar_to_uint64(constNumericVar*var,uint64*result);
475477
#ifdefHAVE_INT128
476478
staticboolnumericvar_to_int128(constNumericVar*var,int128*result);
477479
staticvoidint128_to_numericvar(int128val,NumericVar*var);
@@ -3692,6 +3694,30 @@ numeric_float4(PG_FUNCTION_ARGS)
36923694
}
36933695

36943696

3697+
Datum
3698+
numeric_pg_lsn(PG_FUNCTION_ARGS)
3699+
{
3700+
Numericnum=PG_GETARG_NUMERIC(0);
3701+
NumericVarx;
3702+
XLogRecPtrresult;
3703+
3704+
if (NUMERIC_IS_NAN(num))
3705+
ereport(ERROR,
3706+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3707+
errmsg("cannot convert NaN to pg_lsn")));
3708+
3709+
/* Convert to variable format and thence to pg_lsn */
3710+
init_var_from_num(num,&x);
3711+
3712+
if (!numericvar_to_uint64(&x, (uint64*)&result))
3713+
ereport(ERROR,
3714+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3715+
errmsg("pg_lsn out of range")));
3716+
3717+
PG_RETURN_LSN(result);
3718+
}
3719+
3720+
36953721
/* ----------------------------------------------------------------------
36963722
*
36973723
* Aggregate functions
@@ -6742,6 +6768,78 @@ int64_to_numericvar(int64 val, NumericVar *var)
67426768
var->weight=ndigits-1;
67436769
}
67446770

6771+
/*
6772+
* Convert numeric to uint64, rounding if needed.
6773+
*
6774+
* If overflow, return false (no error is raised). Return true if okay.
6775+
*/
6776+
staticbool
6777+
numericvar_to_uint64(constNumericVar*var,uint64*result)
6778+
{
6779+
NumericDigit*digits;
6780+
intndigits;
6781+
intweight;
6782+
inti;
6783+
uint64val;
6784+
NumericVarrounded;
6785+
6786+
/* Round to nearest integer */
6787+
init_var(&rounded);
6788+
set_var_from_var(var,&rounded);
6789+
round_var(&rounded,0);
6790+
6791+
/* Check for zero input */
6792+
strip_var(&rounded);
6793+
ndigits=rounded.ndigits;
6794+
if (ndigits==0)
6795+
{
6796+
*result=0;
6797+
free_var(&rounded);
6798+
return true;
6799+
}
6800+
6801+
/* Check for negative input */
6802+
if (rounded.sign==NUMERIC_NEG)
6803+
{
6804+
free_var(&rounded);
6805+
return false;
6806+
}
6807+
6808+
/*
6809+
* For input like 10000000000, we must treat stripped digits as real. So
6810+
* the loop assumes there are weight+1 digits before the decimal point.
6811+
*/
6812+
weight=rounded.weight;
6813+
Assert(weight >=0&&ndigits <=weight+1);
6814+
6815+
/* Construct the result */
6816+
digits=rounded.digits;
6817+
val=digits[0];
6818+
for (i=1;i <=weight;i++)
6819+
{
6820+
if (unlikely(pg_mul_u64_overflow(val,NBASE,&val)))
6821+
{
6822+
free_var(&rounded);
6823+
return false;
6824+
}
6825+
6826+
if (i<ndigits)
6827+
{
6828+
if (unlikely(pg_add_u64_overflow(val,digits[i],&val)))
6829+
{
6830+
free_var(&rounded);
6831+
return false;
6832+
}
6833+
}
6834+
}
6835+
6836+
free_var(&rounded);
6837+
6838+
*result=val;
6839+
6840+
return true;
6841+
}
6842+
67456843
#ifdefHAVE_INT128
67466844
/*
67476845
* Convert numeric to int128, rounding if needed.

‎src/backend/utils/adt/pg_lsn.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include"funcapi.h"
1717
#include"libpq/pqformat.h"
1818
#include"utils/builtins.h"
19+
#include"utils/numeric.h"
1920
#include"utils/pg_lsn.h"
2021

2122
#defineMAXPG_LSNLEN17
@@ -248,3 +249,71 @@ pg_lsn_mi(PG_FUNCTION_ARGS)
248249

249250
returnresult;
250251
}
252+
253+
/*
254+
* Add the number of bytes to pg_lsn, giving a new pg_lsn.
255+
* Must handle both positive and negative numbers of bytes.
256+
*/
257+
Datum
258+
pg_lsn_pli(PG_FUNCTION_ARGS)
259+
{
260+
XLogRecPtrlsn=PG_GETARG_LSN(0);
261+
Numericnbytes=PG_GETARG_NUMERIC(1);
262+
Datumnum;
263+
Datumres;
264+
charbuf[32];
265+
266+
if (numeric_is_nan(nbytes))
267+
ereport(ERROR,
268+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
269+
errmsg("cannot add NaN to pg_lsn")));
270+
271+
/* Convert to numeric */
272+
snprintf(buf,sizeof(buf),UINT64_FORMAT,lsn);
273+
num=DirectFunctionCall3(numeric_in,
274+
CStringGetDatum(buf),
275+
ObjectIdGetDatum(0),
276+
Int32GetDatum(-1));
277+
278+
/* Add two numerics */
279+
res=DirectFunctionCall2(numeric_add,
280+
NumericGetDatum(num),
281+
NumericGetDatum(nbytes));
282+
283+
/* Convert to pg_lsn */
284+
returnDirectFunctionCall1(numeric_pg_lsn,res);
285+
}
286+
287+
/*
288+
* Subtract the number of bytes from pg_lsn, giving a new pg_lsn.
289+
* Must handle both positive and negative numbers of bytes.
290+
*/
291+
Datum
292+
pg_lsn_mii(PG_FUNCTION_ARGS)
293+
{
294+
XLogRecPtrlsn=PG_GETARG_LSN(0);
295+
Numericnbytes=PG_GETARG_NUMERIC(1);
296+
Datumnum;
297+
Datumres;
298+
charbuf[32];
299+
300+
if (numeric_is_nan(nbytes))
301+
ereport(ERROR,
302+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
303+
errmsg("cannot subtract NaN from pg_lsn")));
304+
305+
/* Convert to numeric */
306+
snprintf(buf,sizeof(buf),UINT64_FORMAT,lsn);
307+
num=DirectFunctionCall3(numeric_in,
308+
CStringGetDatum(buf),
309+
ObjectIdGetDatum(0),
310+
Int32GetDatum(-1));
311+
312+
/* Subtract two numerics */
313+
res=DirectFunctionCall2(numeric_sub,
314+
NumericGetDatum(num),
315+
NumericGetDatum(nbytes));
316+
317+
/* Convert to pg_lsn */
318+
returnDirectFunctionCall1(numeric_pg_lsn,res);
319+
}

‎src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO202006151
56+
#defineCATALOG_VERSION_NO202006301
5757

5858
#endif

‎src/include/catalog/pg_operator.dat

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,6 +2909,17 @@
29092909
{ oid => '3228', descr => 'minus',
29102910
oprname => '-', oprleft => 'pg_lsn', oprright => 'pg_lsn',
29112911
oprresult => 'numeric', oprcode => 'pg_lsn_mi' },
2912+
{ oid => '5025', descr => 'add',
2913+
oprname => '+', oprleft => 'pg_lsn', oprright => 'numeric',
2914+
oprresult => 'pg_lsn', oprcom => '+(numeric,pg_lsn)',
2915+
oprcode => 'pg_lsn_pli' },
2916+
{ oid => '5026', descr => 'add',
2917+
oprname => '+', oprleft => 'numeric', oprright => 'pg_lsn',
2918+
oprresult => 'pg_lsn', oprcom => '+(pg_lsn,numeric)',
2919+
oprcode => 'numeric_pl_pg_lsn' },
2920+
{ oid => '5027', descr => 'subtract',
2921+
oprname => '-', oprleft => 'pg_lsn', oprright => 'numeric',
2922+
oprresult => 'pg_lsn', oprcode => 'pg_lsn_mii' },
29122923

29132924
# enum operators
29142925
{ oid => '3516', descr => 'equal',

‎src/include/catalog/pg_proc.dat

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4398,6 +4398,9 @@
43984398
{ oid => '1783', descr => 'convert numeric to int2',
43994399
proname => 'int2', prorettype => 'int2', proargtypes => 'numeric',
44004400
prosrc => 'numeric_int2' },
4401+
{ oid => '6103', descr => 'convert numeric to pg_lsn',
4402+
proname => 'pg_lsn', prorettype => 'pg_lsn', proargtypes => 'numeric',
4403+
prosrc => 'numeric_pg_lsn' },
44014404

44024405
{ oid => '3556', descr => 'convert jsonb to boolean',
44034406
proname => 'bool', prorettype => 'bool', proargtypes => 'jsonb',
@@ -8576,6 +8579,15 @@
85768579
{ oid => '4188', descr => 'smaller of two',
85778580
proname => 'pg_lsn_smaller', prorettype => 'pg_lsn',
85788581
proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_smaller' },
8582+
{ oid => '5022',
8583+
proname => 'pg_lsn_pli', prorettype => 'pg_lsn',
8584+
proargtypes => 'pg_lsn numeric', prosrc => 'pg_lsn_pli' },
8585+
{ oid => '5023',
8586+
proname => 'numeric_pl_pg_lsn', prolang => 'sql', prorettype => 'pg_lsn',
8587+
proargtypes => 'numeric pg_lsn', prosrc => 'select $2 + $1' },
8588+
{ oid => '5024',
8589+
proname => 'pg_lsn_mii', prorettype => 'pg_lsn',
8590+
proargtypes => 'pg_lsn numeric', prosrc => 'pg_lsn_mii' },
85798591

85808592
# enum related procs
85818593
{ oid => '3504', descr => 'I/O',

‎src/test/regress/expected/numeric.out

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,3 +2348,30 @@ SELECT -4!;
23482348
ERROR: factorial of a negative number is undefined
23492349
SELECT factorial(-4);
23502350
ERROR: factorial of a negative number is undefined
2351+
--
2352+
-- Tests for pg_lsn()
2353+
--
2354+
SELECT pg_lsn(23783416::numeric);
2355+
pg_lsn
2356+
-----------
2357+
0/16AE7F8
2358+
(1 row)
2359+
2360+
SELECT pg_lsn(0::numeric);
2361+
pg_lsn
2362+
--------
2363+
0/0
2364+
(1 row)
2365+
2366+
SELECT pg_lsn(18446744073709551615::numeric);
2367+
pg_lsn
2368+
-------------------
2369+
FFFFFFFF/FFFFFFFF
2370+
(1 row)
2371+
2372+
SELECT pg_lsn(-1::numeric);
2373+
ERROR: pg_lsn out of range
2374+
SELECT pg_lsn(18446744073709551616::numeric);
2375+
ERROR: pg_lsn out of range
2376+
SELECT pg_lsn('NaN'::numeric);
2377+
ERROR: cannot convert NaN to pg_lsn

‎src/test/regress/expected/pg_lsn.out

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,56 @@ SELECT '0/16AE7F8'::pg_lsn - '0/16AE7F7'::pg_lsn;
7171
1
7272
(1 row)
7373

74+
SELECT '0/16AE7F7'::pg_lsn + 16::numeric;
75+
?column?
76+
-----------
77+
0/16AE807
78+
(1 row)
79+
80+
SELECT 16::numeric + '0/16AE7F7'::pg_lsn;
81+
?column?
82+
-----------
83+
0/16AE807
84+
(1 row)
85+
86+
SELECT '0/16AE7F7'::pg_lsn - 16::numeric;
87+
?column?
88+
-----------
89+
0/16AE7E7
90+
(1 row)
91+
92+
SELECT 'FFFFFFFF/FFFFFFFE'::pg_lsn + 1::numeric;
93+
?column?
94+
-------------------
95+
FFFFFFFF/FFFFFFFF
96+
(1 row)
97+
98+
SELECT 'FFFFFFFF/FFFFFFFE'::pg_lsn + 2::numeric; -- out of range error
99+
ERROR: pg_lsn out of range
100+
SELECT '0/1'::pg_lsn - 1::numeric;
101+
?column?
102+
----------
103+
0/0
104+
(1 row)
105+
106+
SELECT '0/1'::pg_lsn - 2::numeric; -- out of range error
107+
ERROR: pg_lsn out of range
108+
SELECT '0/0'::pg_lsn + ('FFFFFFFF/FFFFFFFF'::pg_lsn - '0/0'::pg_lsn);
109+
?column?
110+
-------------------
111+
FFFFFFFF/FFFFFFFF
112+
(1 row)
113+
114+
SELECT 'FFFFFFFF/FFFFFFFF'::pg_lsn - ('FFFFFFFF/FFFFFFFF'::pg_lsn - '0/0'::pg_lsn);
115+
?column?
116+
----------
117+
0/0
118+
(1 row)
119+
120+
SELECT '0/16AE7F7'::pg_lsn + 'NaN'::numeric;
121+
ERROR: cannot add NaN to pg_lsn
122+
SELECT '0/16AE7F7'::pg_lsn - 'NaN'::numeric;
123+
ERROR: cannot subtract NaN from pg_lsn
74124
-- Check btree and hash opclasses
75125
EXPLAIN (COSTS OFF)
76126
SELECT DISTINCT (i || '/' || j)::pg_lsn f

‎src/test/regress/sql/numeric.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,3 +1122,13 @@ SELECT 100000!;
11221122
SELECT0!;
11231123
SELECT-4!;
11241124
SELECT factorial(-4);
1125+
1126+
--
1127+
-- Tests for pg_lsn()
1128+
--
1129+
SELECT pg_lsn(23783416::numeric);
1130+
SELECT pg_lsn(0::numeric);
1131+
SELECT pg_lsn(18446744073709551615::numeric);
1132+
SELECT pg_lsn(-1::numeric);
1133+
SELECT pg_lsn(18446744073709551616::numeric);
1134+
SELECT pg_lsn('NaN'::numeric);

‎src/test/regress/sql/pg_lsn.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ SELECT '0/16AE7F7' < '0/16AE7F8'::pg_lsn;
2727
SELECT'0/16AE7F8'> pg_lsn'0/16AE7F7';
2828
SELECT'0/16AE7F7'::pg_lsn-'0/16AE7F8'::pg_lsn;
2929
SELECT'0/16AE7F8'::pg_lsn-'0/16AE7F7'::pg_lsn;
30+
SELECT'0/16AE7F7'::pg_lsn+16::numeric;
31+
SELECT16::numeric+'0/16AE7F7'::pg_lsn;
32+
SELECT'0/16AE7F7'::pg_lsn-16::numeric;
33+
SELECT'FFFFFFFF/FFFFFFFE'::pg_lsn+1::numeric;
34+
SELECT'FFFFFFFF/FFFFFFFE'::pg_lsn+2::numeric;-- out of range error
35+
SELECT'0/1'::pg_lsn-1::numeric;
36+
SELECT'0/1'::pg_lsn-2::numeric;-- out of range error
37+
SELECT'0/0'::pg_lsn+ ('FFFFFFFF/FFFFFFFF'::pg_lsn-'0/0'::pg_lsn);
38+
SELECT'FFFFFFFF/FFFFFFFF'::pg_lsn- ('FFFFFFFF/FFFFFFFF'::pg_lsn-'0/0'::pg_lsn);
39+
SELECT'0/16AE7F7'::pg_lsn+'NaN'::numeric;
40+
SELECT'0/16AE7F7'::pg_lsn-'NaN'::numeric;
3041

3142
-- Check btree and hash opclasses
3243
EXPLAIN (COSTS OFF)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp