diff --git a/doc/sql.extensions/README.floating_point_types.md b/doc/sql.extensions/README.floating_point_types.md new file mode 100644 index 0000000000..ecc06efa46 --- /dev/null +++ b/doc/sql.extensions/README.floating_point_types.md @@ -0,0 +1,55 @@ +# Floating point types + +Firebird has two forms of floating point types: + +- approximate numeric types (or binary floating point types) +- decimal floating point types + +## Approximate numeric types + +The approximate numeric types supported by Firebird are a 32 bit single +precision and a 64 bit double precision floating point type. These types are +available with the following SQL standard type names: + +- `REAL` - 32 bit single precision (synonym for `FLOAT`) _(1)_ +- `FLOAT` - 32 bit single precision +- `FLOAT(p)` where `p` is the precision of the significand in binary digits _(2, 3)_ + - 1 <= `p` <= 24 - 32 bit single precision (synonym for `FLOAT`) + - 25 <= `p` <= 53 - 64 bit double precision (synonym for `DOUBLE PRECISION`) +- `DOUBLE PRECISION` - 64 bit double precision + +In addition the following non-standard type names are supported: + +- `LONG FLOAT` - 64 bit double precision (synonym for `DOUBLE PRECISION`) +- `LONG FLOAT(p)` where `p` is the precision of the significand in binary digits _(4, 5)_ + - 1 <= `p` <= 53 - 64 bit double precision (synonym for `DOUBLE PRECISION`) + +These non-standard type names are deprecated and they may be removed in a future +version. + +## Decimal floating point types + +The decimal floating point types supported by Firebird are a 64 bit Decimal64 +with a precision of 16 decimals and a 128 bit Decimal128 with a precision of +34 decimals. These types are available with the following SQL standard type +names: + +- `DECFLOAT` - 128 bit Decimal128 (synonym for `DECFLOAT(34)`) +- `DECFLOAT(16)` - 64 bit Decimal64 +- `DECFLOAT(34)` - 128 bit Decimal128 + +## Notes + +1. `REAL` has been available as a synonym for `FLOAT` since Firebird 1 and even +earlier, but was never documented. +2. Firebird 3 and earlier supported `FLOAT(p)` where `p` was the +approximate precision in decimal digits, and 0 <= `p` <= 7 mapped to 32 bit +single precision and `p` > 7 to 64 bit double precision. This syntax was never +documented. +3. For `p` in `FLOAT(p)`, the values 1 <= `p` <= 24 are all treated as +`p` = 24, values 25 <= `p` <= 53 are all handled as `p` = 53. +4. Firebird 3 and earlier supported `LONG FLOAT(p)` where `p` was the +approximate precision in decimal digits, where any value for `p` mapped to +64 bit double precision. This type name and syntax were never documented. +3. For `p` in `LONG FLOAT(p)`, the values 1 <= `p` <= 53 are all handled as +`p` = 53. diff --git a/src/dsql/parse.y b/src/dsql/parse.y index 5b2a82588c..7362a43b53 100644 --- a/src/dsql/parse.y +++ b/src/dsql/parse.y @@ -5095,11 +5095,19 @@ decimal_keyword %type float_type float_type - : FLOAT precision_opt + : FLOAT precision_opt_nz { + // Precision is binary digits of the significand: 1-24 for 32 bit single precision, 25-53 for 64 bit double precision + // Precision 0 is the 'no precision specified' case, which defaults to 32 bit single precision + SLONG precision = $2; + + if (precision != 0 && (precision < 1 || precision > 53)) + yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(53)); + // Precision must be between 1 and 53 + $$ = newNode(); - if ($2 > 7) + if (precision > 24) { $$->dtype = dtype_double; $$->length = sizeof(double); @@ -5110,8 +5118,16 @@ float_type $$->length = sizeof(float); } } - | LONG FLOAT precision_opt + | LONG FLOAT precision_opt_nz { + // Precision is binary digits of the significand: 1-53 for 64 bit double precision + // Precision 0 is the 'no precision specified case', which defaults to 64 bit double precision + SLONG precision = $3; + + if (precision != 0 && (precision < 1 || precision > 53)) + yyabandon(YYPOSNARG(3), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(53)); + // Precision must be between 1 and 53 + $$ = newNode(); $$->dtype = dtype_double; $$->length = sizeof(double); @@ -5130,13 +5146,7 @@ float_type } ; -%type precision_opt -precision_opt - : /* nothing */ { $$ = 0; } - | '(' nonneg_short_integer ')' { $$ = $2; } - ; - -// alternative to precision_opt that does not allow zero +// optional precision that does not allow zero %type precision_opt_nz precision_opt_nz : /* nothing */ { $$ = 0; }