|
41 | 41 | #include"utils/guc.h"
|
42 | 42 | #include"utils/int8.h"
|
43 | 43 | #include"utils/numeric.h"
|
| 44 | +#include"utils/pg_lsn.h" |
44 | 45 | #include"utils/sortsupport.h"
|
45 | 46 |
|
46 | 47 | /* ----------
|
@@ -472,6 +473,7 @@ static void apply_typmod(NumericVar *var, int32 typmod);
|
472 | 473 | staticboolnumericvar_to_int32(constNumericVar*var,int32*result);
|
473 | 474 | staticboolnumericvar_to_int64(constNumericVar*var,int64*result);
|
474 | 475 | staticvoidint64_to_numericvar(int64val,NumericVar*var);
|
| 476 | +staticboolnumericvar_to_uint64(constNumericVar*var,uint64*result); |
475 | 477 | #ifdefHAVE_INT128
|
476 | 478 | staticboolnumericvar_to_int128(constNumericVar*var,int128*result);
|
477 | 479 | staticvoidint128_to_numericvar(int128val,NumericVar*var);
|
@@ -3692,6 +3694,30 @@ numeric_float4(PG_FUNCTION_ARGS)
|
3692 | 3694 | }
|
3693 | 3695 |
|
3694 | 3696 |
|
| 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 | + |
3695 | 3721 | /* ----------------------------------------------------------------------
|
3696 | 3722 | *
|
3697 | 3723 | * Aggregate functions
|
@@ -6742,6 +6768,78 @@ int64_to_numericvar(int64 val, NumericVar *var)
|
6742 | 6768 | var->weight=ndigits-1;
|
6743 | 6769 | }
|
6744 | 6770 |
|
| 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 | + |
6745 | 6843 | #ifdefHAVE_INT128
|
6746 | 6844 | /*
|
6747 | 6845 | * Convert numeric to int128, rounding if needed.
|
|