mirror of
https://github.com/postgres/postgres.git
synced 2025-06-02 00:01:40 -04:00
Allow underscores in integer and numeric constants.
This allows underscores to be used in integer and numeric literals, and their corresponding type input functions, for visual grouping. For example: 1_500_000_000 3.14159_26535_89793 0xffff_ffff 0b_1001_0001 A single underscore is allowed between any 2 digits, or immediately after the base prefix indicator of non-decimal integers, per SQL:202x draft. Peter Eisentraut and Dean Rasheed Discussion: https://postgr.es/m/84aae844-dc55-a4be-86d9-4f0fa405cc97%40enterprisedb.com
This commit is contained in:
parent
1b6f632a35
commit
faff8f8e47
@ -677,7 +677,8 @@ $function$
|
|||||||
decimal point, if one is used. At least one digit must follow the
|
decimal point, if one is used. At least one digit must follow the
|
||||||
exponent marker (<literal>e</literal>), if one is present.
|
exponent marker (<literal>e</literal>), if one is present.
|
||||||
There cannot be any spaces or other characters embedded in the
|
There cannot be any spaces or other characters embedded in the
|
||||||
constant. Note that any leading plus or minus sign is not actually
|
constant, except for underscores, which can be used for visual grouping as
|
||||||
|
described below. Note that any leading plus or minus sign is not actually
|
||||||
considered part of the constant; it is an operator applied to the
|
considered part of the constant; it is an operator applied to the
|
||||||
constant.
|
constant.
|
||||||
</para>
|
</para>
|
||||||
@ -695,23 +696,24 @@ $function$
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Additionally, non-decimal integer constants can be used in these forms:
|
Additionally, non-decimal integer constants are accepted in these forms:
|
||||||
<synopsis>
|
<synopsis>
|
||||||
0x<replaceable>hexdigits</replaceable>
|
0x<replaceable>hexdigits</replaceable>
|
||||||
0o<replaceable>octdigits</replaceable>
|
0o<replaceable>octdigits</replaceable>
|
||||||
0b<replaceable>bindigits</replaceable>
|
0b<replaceable>bindigits</replaceable>
|
||||||
</synopsis>
|
</synopsis>
|
||||||
<replaceable>hexdigits</replaceable> is one or more hexadecimal digits
|
where <replaceable>hexdigits</replaceable> is one or more hexadecimal digits
|
||||||
(0-9, A-F), <replaceable>octdigits</replaceable> is one or more octal
|
(0-9, A-F), <replaceable>octdigits</replaceable> is one or more octal
|
||||||
digits (0-7), <replaceable>bindigits</replaceable> is one or more binary
|
digits (0-7), and <replaceable>bindigits</replaceable> is one or more binary
|
||||||
digits (0 or 1). Hexadecimal digits and the radix prefixes can be in
|
digits (0 or 1). Hexadecimal digits and the radix prefixes can be in
|
||||||
upper or lower case. Note that only integers can have non-decimal forms,
|
upper or lower case. Note that only integers can have non-decimal forms,
|
||||||
not numbers with fractional parts.
|
not numbers with fractional parts.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
These are some examples of this:
|
These are some examples of valid non-decimal integer constants:
|
||||||
<literallayout>0b100101
|
<literallayout>
|
||||||
|
0b100101
|
||||||
0B10011001
|
0B10011001
|
||||||
0o273
|
0o273
|
||||||
0O755
|
0O755
|
||||||
@ -720,13 +722,21 @@ $function$
|
|||||||
</literallayout>
|
</literallayout>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<para>
|
||||||
<para>
|
For visual grouping, underscores can be inserted between digits. These
|
||||||
Non-decimal integer constants are currently only supported in the range
|
have no further effect on the value of the constant. For example:
|
||||||
of the <type>bigint</type> type (see <xref
|
<literallayout>
|
||||||
linkend="datatype-numeric-table"/>).
|
1_500_000_000
|
||||||
</para>
|
0b10001000_00000000
|
||||||
</note>
|
0o_1_755
|
||||||
|
0xFFFF_FFFF
|
||||||
|
1.618_034
|
||||||
|
</literallayout>
|
||||||
|
Underscores are not allowed at the start or end of a numeric constant or
|
||||||
|
a group of digits (that is, immediately before or after the decimal point
|
||||||
|
or the exponent marker), and more than one underscore in a row is not
|
||||||
|
allowed.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<indexterm><primary>integer</primary></indexterm>
|
<indexterm><primary>integer</primary></indexterm>
|
||||||
|
@ -528,6 +528,7 @@ T653 SQL-schema statements in external routines YES
|
|||||||
T654 SQL-dynamic statements in external routines NO
|
T654 SQL-dynamic statements in external routines NO
|
||||||
T655 Cyclically dependent routines YES
|
T655 Cyclically dependent routines YES
|
||||||
T661 Non-decimal integer literals YES SQL:202x draft
|
T661 Non-decimal integer literals YES SQL:202x draft
|
||||||
|
T662 Underscores in integer literals YES SQL:202x draft
|
||||||
T811 Basic SQL/JSON constructor functions NO
|
T811 Basic SQL/JSON constructor functions NO
|
||||||
T812 SQL/JSON: JSON_OBJECTAGG NO
|
T812 SQL/JSON: JSON_OBJECTAGG NO
|
||||||
T813 SQL/JSON: JSON_ARRAYAGG with ORDER BY NO
|
T813 SQL/JSON: JSON_ARRAYAGG with ORDER BY NO
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "mb/pg_wchar.h"
|
#include "mb/pg_wchar.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
|
#include "nodes/miscnodes.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
#include "nodes/subscripting.h"
|
#include "nodes/subscripting.h"
|
||||||
#include "parser/parse_coerce.h"
|
#include "parser/parse_coerce.h"
|
||||||
@ -385,47 +386,11 @@ make_const(ParseState *pstate, A_Const *aconst)
|
|||||||
{
|
{
|
||||||
/* could be an oversize integer as well as a float ... */
|
/* could be an oversize integer as well as a float ... */
|
||||||
|
|
||||||
int base = 10;
|
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||||
char *startptr;
|
|
||||||
int sign;
|
|
||||||
char *testvalue;
|
|
||||||
int64 val64;
|
int64 val64;
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
startptr = aconst->val.fval.fval;
|
val64 = pg_strtoint64_safe(aconst->val.fval.fval, (Node *) &escontext);
|
||||||
if (startptr[0] == '-')
|
if (!escontext.error_occurred)
|
||||||
{
|
|
||||||
sign = -1;
|
|
||||||
startptr++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sign = +1;
|
|
||||||
if (startptr[0] == '0')
|
|
||||||
{
|
|
||||||
if (startptr[1] == 'b' || startptr[1] == 'B')
|
|
||||||
{
|
|
||||||
base = 2;
|
|
||||||
startptr += 2;
|
|
||||||
}
|
|
||||||
else if (startptr[1] == 'o' || startptr[1] == 'O')
|
|
||||||
{
|
|
||||||
base = 8;
|
|
||||||
startptr += 2;
|
|
||||||
}
|
|
||||||
else if (startptr[1] == 'x' || startptr[1] == 'X')
|
|
||||||
{
|
|
||||||
base = 16;
|
|
||||||
startptr += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sign == +1)
|
|
||||||
testvalue = startptr;
|
|
||||||
else
|
|
||||||
testvalue = psprintf("-%s", startptr);
|
|
||||||
errno = 0;
|
|
||||||
val64 = strtoi64(testvalue, &endptr, base);
|
|
||||||
if (errno == 0 && *endptr == '\0')
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* It might actually fit in int32. Probably only INT_MIN
|
* It might actually fit in int32. Probably only INT_MIN
|
||||||
|
@ -37,10 +37,12 @@
|
|||||||
|
|
||||||
#include "common/string.h"
|
#include "common/string.h"
|
||||||
#include "gramparse.h"
|
#include "gramparse.h"
|
||||||
|
#include "nodes/miscnodes.h"
|
||||||
#include "parser/parser.h" /* only needed for GUC variables */
|
#include "parser/parser.h" /* only needed for GUC variables */
|
||||||
#include "parser/scansup.h"
|
#include "parser/scansup.h"
|
||||||
#include "port/pg_bitutils.h"
|
#include "port/pg_bitutils.h"
|
||||||
#include "mb/pg_wchar.h"
|
#include "mb/pg_wchar.h"
|
||||||
|
#include "utils/builtins.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
@ -395,19 +397,19 @@ hexdigit [0-9A-Fa-f]
|
|||||||
octdigit [0-7]
|
octdigit [0-7]
|
||||||
bindigit [0-1]
|
bindigit [0-1]
|
||||||
|
|
||||||
decinteger {decdigit}+
|
decinteger {decdigit}(_?{decdigit})*
|
||||||
hexinteger 0[xX]{hexdigit}+
|
hexinteger 0[xX](_?{hexdigit})+
|
||||||
octinteger 0[oO]{octdigit}+
|
octinteger 0[oO](_?{octdigit})+
|
||||||
bininteger 0[bB]{bindigit}+
|
bininteger 0[bB](_?{bindigit})+
|
||||||
|
|
||||||
hexfail 0[xX]
|
hexfail 0[xX]_?
|
||||||
octfail 0[oO]
|
octfail 0[oO]_?
|
||||||
binfail 0[bB]
|
binfail 0[bB]_?
|
||||||
|
|
||||||
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
|
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
|
||||||
numericfail {decdigit}+\.\.
|
numericfail {decdigit}+\.\.
|
||||||
|
|
||||||
real ({decinteger}|{numeric})[Ee][-+]?{decdigit}+
|
real ({decinteger}|{numeric})[Ee][-+]?{decinteger}
|
||||||
realfail ({decinteger}|{numeric})[Ee][-+]
|
realfail ({decinteger}|{numeric})[Ee][-+]
|
||||||
|
|
||||||
decinteger_junk {decinteger}{ident_start}
|
decinteger_junk {decinteger}{ident_start}
|
||||||
@ -1364,12 +1366,11 @@ litbufdup(core_yyscan_t yyscanner)
|
|||||||
static int
|
static int
|
||||||
process_integer_literal(const char *token, YYSTYPE *lval, int base)
|
process_integer_literal(const char *token, YYSTYPE *lval, int base)
|
||||||
{
|
{
|
||||||
int val;
|
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||||
char *endptr;
|
int32 val;
|
||||||
|
|
||||||
errno = 0;
|
val = pg_strtoint32_safe(token, (Node *) &escontext);
|
||||||
val = strtoint(base == 10 ? token : token + 2, &endptr, base);
|
if (escontext.error_occurred)
|
||||||
if (*endptr != '\0' || errno == ERANGE)
|
|
||||||
{
|
{
|
||||||
/* integer too large (or contains decimal pt), treat it as a float */
|
/* integer too large (or contains decimal pt), treat it as a float */
|
||||||
lval->str = pstrdup(token);
|
lval->str = pstrdup(token);
|
||||||
|
@ -6968,10 +6968,7 @@ set_var_from_str(const char *str, const char *cp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isdigit((unsigned char) *cp))
|
if (!isdigit((unsigned char) *cp))
|
||||||
ereturn(escontext, false,
|
goto invalid_syntax;
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
|
||||||
"numeric", str)));
|
|
||||||
|
|
||||||
decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
|
decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
|
||||||
|
|
||||||
@ -6992,12 +6989,19 @@ set_var_from_str(const char *str, const char *cp,
|
|||||||
else if (*cp == '.')
|
else if (*cp == '.')
|
||||||
{
|
{
|
||||||
if (have_dp)
|
if (have_dp)
|
||||||
ereturn(escontext, false,
|
goto invalid_syntax;
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
|
||||||
"numeric", str)));
|
|
||||||
have_dp = true;
|
have_dp = true;
|
||||||
cp++;
|
cp++;
|
||||||
|
/* decimal point must not be followed by underscore */
|
||||||
|
if (*cp == '_')
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else if (*cp == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
cp++;
|
||||||
|
if (!isdigit((unsigned char) *cp))
|
||||||
|
goto invalid_syntax;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@ -7010,17 +7014,8 @@ set_var_from_str(const char *str, const char *cp,
|
|||||||
/* Handle exponent, if any */
|
/* Handle exponent, if any */
|
||||||
if (*cp == 'e' || *cp == 'E')
|
if (*cp == 'e' || *cp == 'E')
|
||||||
{
|
{
|
||||||
long exponent;
|
int64 exponent = 0;
|
||||||
char *endptr;
|
bool neg = false;
|
||||||
|
|
||||||
cp++;
|
|
||||||
exponent = strtol(cp, &endptr, 10);
|
|
||||||
if (endptr == cp)
|
|
||||||
ereturn(escontext, false,
|
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
|
||||||
"numeric", str)));
|
|
||||||
cp = endptr;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point, dweight and dscale can't be more than about
|
* At this point, dweight and dscale can't be more than about
|
||||||
@ -7030,10 +7025,43 @@ set_var_from_str(const char *str, const char *cp,
|
|||||||
* fit in storage format, make_result() will complain about it later;
|
* fit in storage format, make_result() will complain about it later;
|
||||||
* for consistency use the same ereport errcode/text as make_result().
|
* for consistency use the same ereport errcode/text as make_result().
|
||||||
*/
|
*/
|
||||||
if (exponent >= INT_MAX / 2 || exponent <= -(INT_MAX / 2))
|
|
||||||
ereturn(escontext, false,
|
/* exponent sign */
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
cp++;
|
||||||
errmsg("value overflows numeric format")));
|
if (*cp == '+')
|
||||||
|
cp++;
|
||||||
|
else if (*cp == '-')
|
||||||
|
{
|
||||||
|
neg = true;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* exponent digits */
|
||||||
|
if (!isdigit((unsigned char) *cp))
|
||||||
|
goto invalid_syntax;
|
||||||
|
|
||||||
|
while (*cp)
|
||||||
|
{
|
||||||
|
if (isdigit((unsigned char) *cp))
|
||||||
|
{
|
||||||
|
exponent = exponent * 10 + (*cp++ - '0');
|
||||||
|
if (exponent > PG_INT32_MAX / 2)
|
||||||
|
goto out_of_range;
|
||||||
|
}
|
||||||
|
else if (*cp == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
cp++;
|
||||||
|
if (!isdigit((unsigned char) *cp))
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (neg)
|
||||||
|
exponent = -exponent;
|
||||||
|
|
||||||
dweight += (int) exponent;
|
dweight += (int) exponent;
|
||||||
dscale -= (int) exponent;
|
dscale -= (int) exponent;
|
||||||
if (dscale < 0)
|
if (dscale < 0)
|
||||||
@ -7085,6 +7113,17 @@ set_var_from_str(const char *str, const char *cp,
|
|||||||
*endptr = cp;
|
*endptr = cp;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
out_of_range:
|
||||||
|
ereturn(escontext, false,
|
||||||
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
|
errmsg("value overflows numeric format")));
|
||||||
|
|
||||||
|
invalid_syntax:
|
||||||
|
ereturn(escontext, false,
|
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
|
"numeric", str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7167,6 +7206,13 @@ set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
|
|||||||
tmp = tmp * 16 + xdigit_value(*cp++);
|
tmp = tmp * 16 + xdigit_value(*cp++);
|
||||||
mul = mul * 16;
|
mul = mul * 16;
|
||||||
}
|
}
|
||||||
|
else if (*cp == '_')
|
||||||
|
{
|
||||||
|
/* Underscore must be followed by more digits */
|
||||||
|
cp++;
|
||||||
|
if (!isxdigit((unsigned char) *cp))
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -7197,6 +7243,13 @@ set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
|
|||||||
tmp = tmp * 8 + (*cp++ - '0');
|
tmp = tmp * 8 + (*cp++ - '0');
|
||||||
mul = mul * 8;
|
mul = mul * 8;
|
||||||
}
|
}
|
||||||
|
else if (*cp == '_')
|
||||||
|
{
|
||||||
|
/* Underscore must be followed by more digits */
|
||||||
|
cp++;
|
||||||
|
if (*cp < '0' || *cp > '7')
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -7227,6 +7280,13 @@ set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
|
|||||||
tmp = tmp * 2 + (*cp++ - '0');
|
tmp = tmp * 2 + (*cp++ - '0');
|
||||||
mul = mul * 2;
|
mul = mul * 2;
|
||||||
}
|
}
|
||||||
|
else if (*cp == '_')
|
||||||
|
{
|
||||||
|
/* Underscore must be followed by more digits */
|
||||||
|
cp++;
|
||||||
|
if (*cp < '0' || *cp > '1')
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -141,48 +141,99 @@ pg_strtoint16_safe(const char *s, Node *escontext)
|
|||||||
{
|
{
|
||||||
firstdigit = ptr += 2;
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
while (*ptr && isxdigit((unsigned char) *ptr))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT16_MIN / 16)))
|
if (isxdigit((unsigned char) *ptr))
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT16_MIN / 16)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
|
tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
|
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
|
||||||
{
|
{
|
||||||
firstdigit = ptr += 2;
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
while (*ptr && (*ptr >= '0' && *ptr <= '7'))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT16_MIN / 8)))
|
if (*ptr >= '0' && *ptr <= '7')
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT16_MIN / 8)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 8 + (*ptr++ - '0');
|
tmp = tmp * 8 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
|
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
|
||||||
{
|
{
|
||||||
firstdigit = ptr += 2;
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
while (*ptr && (*ptr >= '0' && *ptr <= '1'))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT16_MIN / 2)))
|
if (*ptr >= '0' && *ptr <= '1')
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT16_MIN / 2)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 2 + (*ptr++ - '0');
|
tmp = tmp * 2 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
firstdigit = ptr;
|
firstdigit = ptr;
|
||||||
|
|
||||||
while (*ptr && isdigit((unsigned char) *ptr))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT16_MIN / 10)))
|
if (isdigit((unsigned char) *ptr))
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT16_MIN / 10)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 10 + (*ptr++ - '0');
|
tmp = tmp * 10 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore may not be first */
|
||||||
|
if (unlikely(ptr == firstdigit))
|
||||||
|
goto invalid_syntax;
|
||||||
|
/* and it must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,48 +319,99 @@ pg_strtoint32_safe(const char *s, Node *escontext)
|
|||||||
{
|
{
|
||||||
firstdigit = ptr += 2;
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
while (*ptr && isxdigit((unsigned char) *ptr))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT32_MIN / 16)))
|
if (isxdigit((unsigned char) *ptr))
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT32_MIN / 16)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
|
tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
|
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
|
||||||
{
|
{
|
||||||
firstdigit = ptr += 2;
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
while (*ptr && (*ptr >= '0' && *ptr <= '7'))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT32_MIN / 8)))
|
if (*ptr >= '0' && *ptr <= '7')
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT32_MIN / 8)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 8 + (*ptr++ - '0');
|
tmp = tmp * 8 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
|
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
|
||||||
{
|
{
|
||||||
firstdigit = ptr += 2;
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
while (*ptr && (*ptr >= '0' && *ptr <= '1'))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT32_MIN / 2)))
|
if (*ptr >= '0' && *ptr <= '1')
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT32_MIN / 2)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 2 + (*ptr++ - '0');
|
tmp = tmp * 2 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
firstdigit = ptr;
|
firstdigit = ptr;
|
||||||
|
|
||||||
while (*ptr && isdigit((unsigned char) *ptr))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT32_MIN / 10)))
|
if (isdigit((unsigned char) *ptr))
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT32_MIN / 10)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 10 + (*ptr++ - '0');
|
tmp = tmp * 10 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore may not be first */
|
||||||
|
if (unlikely(ptr == firstdigit))
|
||||||
|
goto invalid_syntax;
|
||||||
|
/* and it must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,48 +497,99 @@ pg_strtoint64_safe(const char *s, Node *escontext)
|
|||||||
{
|
{
|
||||||
firstdigit = ptr += 2;
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
while (*ptr && isxdigit((unsigned char) *ptr))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT64_MIN / 16)))
|
if (isxdigit((unsigned char) *ptr))
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT64_MIN / 16)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
|
tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
|
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
|
||||||
{
|
{
|
||||||
firstdigit = ptr += 2;
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
while (*ptr && (*ptr >= '0' && *ptr <= '7'))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT64_MIN / 8)))
|
if (*ptr >= '0' && *ptr <= '7')
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT64_MIN / 8)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 8 + (*ptr++ - '0');
|
tmp = tmp * 8 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
|
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
|
||||||
{
|
{
|
||||||
firstdigit = ptr += 2;
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
while (*ptr && (*ptr >= '0' && *ptr <= '1'))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT64_MIN / 2)))
|
if (*ptr >= '0' && *ptr <= '1')
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT64_MIN / 2)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 2 + (*ptr++ - '0');
|
tmp = tmp * 2 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
firstdigit = ptr;
|
firstdigit = ptr;
|
||||||
|
|
||||||
while (*ptr && isdigit((unsigned char) *ptr))
|
while (*ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT64_MIN / 10)))
|
if (isdigit((unsigned char) *ptr))
|
||||||
goto out_of_range;
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT64_MIN / 10)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
tmp = tmp * 10 + (*ptr++ - '0');
|
tmp = tmp * 10 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
else if (*ptr == '_')
|
||||||
|
{
|
||||||
|
/* underscore may not be first */
|
||||||
|
if (unlikely(ptr == firstdigit))
|
||||||
|
goto invalid_syntax;
|
||||||
|
/* and it must be followed by more digits */
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
|
||||||
|
goto invalid_syntax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,19 +333,19 @@ hexdigit [0-9A-Fa-f]
|
|||||||
octdigit [0-7]
|
octdigit [0-7]
|
||||||
bindigit [0-1]
|
bindigit [0-1]
|
||||||
|
|
||||||
decinteger {decdigit}+
|
decinteger {decdigit}(_?{decdigit})*
|
||||||
hexinteger 0[xX]{hexdigit}+
|
hexinteger 0[xX](_?{hexdigit})+
|
||||||
octinteger 0[oO]{octdigit}+
|
octinteger 0[oO](_?{octdigit})+
|
||||||
bininteger 0[bB]{bindigit}+
|
bininteger 0[bB](_?{bindigit})+
|
||||||
|
|
||||||
hexfail 0[xX]
|
hexfail 0[xX]_?
|
||||||
octfail 0[oO]
|
octfail 0[oO]_?
|
||||||
binfail 0[bB]
|
binfail 0[bB]_?
|
||||||
|
|
||||||
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
|
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
|
||||||
numericfail {decdigit}+\.\.
|
numericfail {decdigit}+\.\.
|
||||||
|
|
||||||
real ({decinteger}|{numeric})[Ee][-+]?{decdigit}+
|
real ({decinteger}|{numeric})[Ee][-+]?{decinteger}
|
||||||
realfail ({decinteger}|{numeric})[Ee][-+]
|
realfail ({decinteger}|{numeric})[Ee][-+]
|
||||||
|
|
||||||
decinteger_junk {decinteger}{ident_start}
|
decinteger_junk {decinteger}{ident_start}
|
||||||
|
@ -361,19 +361,19 @@ hexdigit [0-9A-Fa-f]
|
|||||||
octdigit [0-7]
|
octdigit [0-7]
|
||||||
bindigit [0-1]
|
bindigit [0-1]
|
||||||
|
|
||||||
decinteger {decdigit}+
|
decinteger {decdigit}(_?{decdigit})*
|
||||||
hexinteger 0[xX]{hexdigit}+
|
hexinteger 0[xX](_?{hexdigit})+
|
||||||
octinteger 0[oO]{octdigit}+
|
octinteger 0[oO](_?{octdigit})+
|
||||||
bininteger 0[bB]{bindigit}+
|
bininteger 0[bB](_?{bindigit})+
|
||||||
|
|
||||||
hexfail 0[xX]
|
hexfail 0[xX]_?
|
||||||
octfail 0[oO]
|
octfail 0[oO]_?
|
||||||
binfail 0[bB]
|
binfail 0[bB]_?
|
||||||
|
|
||||||
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
|
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
|
||||||
numericfail {decdigit}+\.\.
|
numericfail {decdigit}+\.\.
|
||||||
|
|
||||||
real ({decinteger}|{numeric})[Ee][-+]?{decdigit}+
|
real ({decinteger}|{numeric})[Ee][-+]?{decinteger}
|
||||||
realfail ({decinteger}|{numeric})[Ee][-+]
|
realfail ({decinteger}|{numeric})[Ee][-+]
|
||||||
|
|
||||||
decinteger_junk {decinteger}{ident_start}
|
decinteger_junk {decinteger}{ident_start}
|
||||||
|
@ -141,7 +141,7 @@ begin
|
|||||||
declare x int;
|
declare x int;
|
||||||
begin
|
begin
|
||||||
-- we assume this will take longer than 1 second:
|
-- we assume this will take longer than 1 second:
|
||||||
select count(*) into x from generate_series(1, 1000000000000);
|
select count(*) into x from generate_series(1, 1_000_000_000_000);
|
||||||
exception
|
exception
|
||||||
when others then
|
when others then
|
||||||
raise notice 'caught others?';
|
raise notice 'caught others?';
|
||||||
|
@ -88,7 +88,7 @@ begin
|
|||||||
declare x int;
|
declare x int;
|
||||||
begin
|
begin
|
||||||
-- we assume this will take longer than 1 second:
|
-- we assume this will take longer than 1 second:
|
||||||
select count(*) into x from generate_series(1, 1000000000000);
|
select count(*) into x from generate_series(1, 1_000_000_000_000);
|
||||||
exception
|
exception
|
||||||
when others then
|
when others then
|
||||||
raise notice 'caught others?';
|
raise notice 'caught others?';
|
||||||
|
@ -440,3 +440,47 @@ SELECT int2 '-0x8001';
|
|||||||
ERROR: value "-0x8001" is out of range for type smallint
|
ERROR: value "-0x8001" is out of range for type smallint
|
||||||
LINE 1: SELECT int2 '-0x8001';
|
LINE 1: SELECT int2 '-0x8001';
|
||||||
^
|
^
|
||||||
|
-- underscores
|
||||||
|
SELECT int2 '1_000';
|
||||||
|
int2
|
||||||
|
------
|
||||||
|
1000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '1_2_3';
|
||||||
|
int2
|
||||||
|
------
|
||||||
|
123
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '0xE_FF';
|
||||||
|
int2
|
||||||
|
------
|
||||||
|
3839
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '0o2_73';
|
||||||
|
int2
|
||||||
|
------
|
||||||
|
187
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '0b_10_0101';
|
||||||
|
int2
|
||||||
|
------
|
||||||
|
37
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- error cases
|
||||||
|
SELECT int2 '_100';
|
||||||
|
ERROR: invalid input syntax for type smallint: "_100"
|
||||||
|
LINE 1: SELECT int2 '_100';
|
||||||
|
^
|
||||||
|
SELECT int2 '100_';
|
||||||
|
ERROR: invalid input syntax for type smallint: "100_"
|
||||||
|
LINE 1: SELECT int2 '100_';
|
||||||
|
^
|
||||||
|
SELECT int2 '10__000';
|
||||||
|
ERROR: invalid input syntax for type smallint: "10__000"
|
||||||
|
LINE 1: SELECT int2 '10__000';
|
||||||
|
^
|
||||||
|
@ -548,3 +548,47 @@ SELECT int4 '-0x80000001';
|
|||||||
ERROR: value "-0x80000001" is out of range for type integer
|
ERROR: value "-0x80000001" is out of range for type integer
|
||||||
LINE 1: SELECT int4 '-0x80000001';
|
LINE 1: SELECT int4 '-0x80000001';
|
||||||
^
|
^
|
||||||
|
-- underscores
|
||||||
|
SELECT int4 '1_000_000';
|
||||||
|
int4
|
||||||
|
---------
|
||||||
|
1000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '1_2_3';
|
||||||
|
int4
|
||||||
|
------
|
||||||
|
123
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '0x1EEE_FFFF';
|
||||||
|
int4
|
||||||
|
-----------
|
||||||
|
518979583
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '0o2_73';
|
||||||
|
int4
|
||||||
|
------
|
||||||
|
187
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '0b_10_0101';
|
||||||
|
int4
|
||||||
|
------
|
||||||
|
37
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- error cases
|
||||||
|
SELECT int4 '_100';
|
||||||
|
ERROR: invalid input syntax for type integer: "_100"
|
||||||
|
LINE 1: SELECT int4 '_100';
|
||||||
|
^
|
||||||
|
SELECT int4 '100_';
|
||||||
|
ERROR: invalid input syntax for type integer: "100_"
|
||||||
|
LINE 1: SELECT int4 '100_';
|
||||||
|
^
|
||||||
|
SELECT int4 '100__000';
|
||||||
|
ERROR: invalid input syntax for type integer: "100__000"
|
||||||
|
LINE 1: SELECT int4 '100__000';
|
||||||
|
^
|
||||||
|
@ -1044,3 +1044,47 @@ SELECT int8 '-0x8000000000000001';
|
|||||||
ERROR: value "-0x8000000000000001" is out of range for type bigint
|
ERROR: value "-0x8000000000000001" is out of range for type bigint
|
||||||
LINE 1: SELECT int8 '-0x8000000000000001';
|
LINE 1: SELECT int8 '-0x8000000000000001';
|
||||||
^
|
^
|
||||||
|
-- underscores
|
||||||
|
SELECT int8 '1_000_000';
|
||||||
|
int8
|
||||||
|
---------
|
||||||
|
1000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '1_2_3';
|
||||||
|
int8
|
||||||
|
------
|
||||||
|
123
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '0x1EEE_FFFF';
|
||||||
|
int8
|
||||||
|
-----------
|
||||||
|
518979583
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '0o2_73';
|
||||||
|
int8
|
||||||
|
------
|
||||||
|
187
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '0b_10_0101';
|
||||||
|
int8
|
||||||
|
------
|
||||||
|
37
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- error cases
|
||||||
|
SELECT int8 '_100';
|
||||||
|
ERROR: invalid input syntax for type bigint: "_100"
|
||||||
|
LINE 1: SELECT int8 '_100';
|
||||||
|
^
|
||||||
|
SELECT int8 '100_';
|
||||||
|
ERROR: invalid input syntax for type bigint: "100_"
|
||||||
|
LINE 1: SELECT int8 '100_';
|
||||||
|
^
|
||||||
|
SELECT int8 '100__000';
|
||||||
|
ERROR: invalid input syntax for type bigint: "100__000"
|
||||||
|
LINE 1: SELECT int8 '100__000';
|
||||||
|
^
|
||||||
|
@ -2144,12 +2144,17 @@ INSERT INTO num_input_test(n1) VALUES (' -inf ');
|
|||||||
INSERT INTO num_input_test(n1) VALUES (' Infinity ');
|
INSERT INTO num_input_test(n1) VALUES (' Infinity ');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' +inFinity ');
|
INSERT INTO num_input_test(n1) VALUES (' +inFinity ');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' -INFINITY ');
|
INSERT INTO num_input_test(n1) VALUES (' -INFINITY ');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('12_000_000_000');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('12_000.123_456');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('23_000_000_000e-1_0');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('.000_000_000_123e1_0');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('.000_000_000_123e+1_1');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('0b10001110111100111100001001010');
|
INSERT INTO num_input_test(n1) VALUES ('0b10001110111100111100001001010');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' -0B1010101101010100101010011000110011101011000111110000101011010010 ');
|
INSERT INTO num_input_test(n1) VALUES (' -0B_1010_1011_0101_0100_1010_1001_1000_1100_1110_1011_0001_1111_0000_1010_1101_0010 ');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' +0o112402761777 ');
|
INSERT INTO num_input_test(n1) VALUES (' +0o112402761777 ');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('-0O001255245230633431670261');
|
INSERT INTO num_input_test(n1) VALUES ('-0O0012_5524_5230_6334_3167_0261');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('-0x0000000000000000000000000deadbeef');
|
INSERT INTO num_input_test(n1) VALUES ('-0x0000000000000000000000000deadbeef');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' 0X30b1F33a6DF0bD4E64DF9BdA7D15 ');
|
INSERT INTO num_input_test(n1) VALUES (' 0X_30b1_F33a_6DF0_bD4E_64DF_9BdA_7D15 ');
|
||||||
-- bad inputs
|
-- bad inputs
|
||||||
INSERT INTO num_input_test(n1) VALUES (' ');
|
INSERT INTO num_input_test(n1) VALUES (' ');
|
||||||
ERROR: invalid input syntax for type numeric: " "
|
ERROR: invalid input syntax for type numeric: " "
|
||||||
@ -2195,6 +2200,38 @@ INSERT INTO num_input_test(n1) VALUES ('+ infinity');
|
|||||||
ERROR: invalid input syntax for type numeric: "+ infinity"
|
ERROR: invalid input syntax for type numeric: "+ infinity"
|
||||||
LINE 1: INSERT INTO num_input_test(n1) VALUES ('+ infinity');
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('+ infinity');
|
||||||
^
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('_123');
|
||||||
|
ERROR: invalid input syntax for type numeric: "_123"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('_123');
|
||||||
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('123_');
|
||||||
|
ERROR: invalid input syntax for type numeric: "123_"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('123_');
|
||||||
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('12__34');
|
||||||
|
ERROR: invalid input syntax for type numeric: "12__34"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('12__34');
|
||||||
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('123_.456');
|
||||||
|
ERROR: invalid input syntax for type numeric: "123_.456"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('123_.456');
|
||||||
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('123._456');
|
||||||
|
ERROR: invalid input syntax for type numeric: "123._456"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('123._456');
|
||||||
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('1.2e_34');
|
||||||
|
ERROR: invalid input syntax for type numeric: "1.2e_34"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('1.2e_34');
|
||||||
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('1.2e34_');
|
||||||
|
ERROR: invalid input syntax for type numeric: "1.2e34_"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('1.2e34_');
|
||||||
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('1.2e3__4');
|
||||||
|
ERROR: invalid input syntax for type numeric: "1.2e3__4"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('1.2e3__4');
|
||||||
|
^
|
||||||
INSERT INTO num_input_test(n1) VALUES ('0b1112');
|
INSERT INTO num_input_test(n1) VALUES ('0b1112');
|
||||||
ERROR: invalid input syntax for type numeric: "0b1112"
|
ERROR: invalid input syntax for type numeric: "0b1112"
|
||||||
LINE 1: INSERT INTO num_input_test(n1) VALUES ('0b1112');
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('0b1112');
|
||||||
@ -2215,6 +2252,18 @@ INSERT INTO num_input_test(n1) VALUES ('0x12.34');
|
|||||||
ERROR: invalid input syntax for type numeric: "0x12.34"
|
ERROR: invalid input syntax for type numeric: "0x12.34"
|
||||||
LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x12.34');
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x12.34');
|
||||||
^
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('0x__1234');
|
||||||
|
ERROR: invalid input syntax for type numeric: "0x__1234"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x__1234');
|
||||||
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('0x1234_');
|
||||||
|
ERROR: invalid input syntax for type numeric: "0x1234_"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x1234_');
|
||||||
|
^
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('0x12__34');
|
||||||
|
ERROR: invalid input syntax for type numeric: "0x12__34"
|
||||||
|
LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x12__34');
|
||||||
|
^
|
||||||
SELECT * FROM num_input_test;
|
SELECT * FROM num_input_test;
|
||||||
n1
|
n1
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
@ -2231,13 +2280,18 @@ SELECT * FROM num_input_test;
|
|||||||
Infinity
|
Infinity
|
||||||
Infinity
|
Infinity
|
||||||
-Infinity
|
-Infinity
|
||||||
|
12000000000
|
||||||
|
12000.123456
|
||||||
|
2.3000000000
|
||||||
|
1.23
|
||||||
|
12.3
|
||||||
299792458
|
299792458
|
||||||
-12345678901234567890
|
-12345678901234567890
|
||||||
9999999999
|
9999999999
|
||||||
-12345678900987654321
|
-12345678900987654321
|
||||||
-3735928559
|
-3735928559
|
||||||
987654321234567898765432123456789
|
987654321234567898765432123456789
|
||||||
(19 rows)
|
(24 rows)
|
||||||
|
|
||||||
-- Also try it with non-error-throwing API
|
-- Also try it with non-error-throwing API
|
||||||
SELECT pg_input_is_valid('34.5', 'numeric');
|
SELECT pg_input_is_valid('34.5', 'numeric');
|
||||||
|
@ -178,10 +178,6 @@ SELECT 0x0o;
|
|||||||
ERROR: trailing junk after numeric literal at or near "0x0o"
|
ERROR: trailing junk after numeric literal at or near "0x0o"
|
||||||
LINE 1: SELECT 0x0o;
|
LINE 1: SELECT 0x0o;
|
||||||
^
|
^
|
||||||
SELECT 1_2_3;
|
|
||||||
ERROR: trailing junk after numeric literal at or near "1_"
|
|
||||||
LINE 1: SELECT 1_2_3;
|
|
||||||
^
|
|
||||||
SELECT 0.a;
|
SELECT 0.a;
|
||||||
ERROR: trailing junk after numeric literal at or near "0.a"
|
ERROR: trailing junk after numeric literal at or near "0.a"
|
||||||
LINE 1: SELECT 0.a;
|
LINE 1: SELECT 0.a;
|
||||||
@ -246,6 +242,94 @@ SELECT 0x0y;
|
|||||||
ERROR: trailing junk after numeric literal at or near "0x0y"
|
ERROR: trailing junk after numeric literal at or near "0x0y"
|
||||||
LINE 1: SELECT 0x0y;
|
LINE 1: SELECT 0x0y;
|
||||||
^
|
^
|
||||||
|
-- underscores
|
||||||
|
SELECT 1_000_000;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
1000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 1_2_3;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
123
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0x1EEE_FFFF;
|
||||||
|
?column?
|
||||||
|
-----------
|
||||||
|
518979583
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0o2_73;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
187
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0b_10_0101;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
37
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 1_000.000_005;
|
||||||
|
?column?
|
||||||
|
-------------
|
||||||
|
1000.000005
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 1_000.;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
1000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT .000_005;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
0.000005
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 1_000.5e0_1;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
10005
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- error cases
|
||||||
|
SELECT _100;
|
||||||
|
ERROR: column "_100" does not exist
|
||||||
|
LINE 1: SELECT _100;
|
||||||
|
^
|
||||||
|
SELECT 100_;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "100_"
|
||||||
|
LINE 1: SELECT 100_;
|
||||||
|
^
|
||||||
|
SELECT 100__000;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "100_"
|
||||||
|
LINE 1: SELECT 100__000;
|
||||||
|
^
|
||||||
|
SELECT _1_000.5;
|
||||||
|
ERROR: syntax error at or near ".5"
|
||||||
|
LINE 1: SELECT _1_000.5;
|
||||||
|
^
|
||||||
|
SELECT 1_000_.5;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "1_000_"
|
||||||
|
LINE 1: SELECT 1_000_.5;
|
||||||
|
^
|
||||||
|
SELECT 1_000._5;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "1_000._"
|
||||||
|
LINE 1: SELECT 1_000._5;
|
||||||
|
^
|
||||||
|
SELECT 1_000.5_;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "1_000.5_"
|
||||||
|
LINE 1: SELECT 1_000.5_;
|
||||||
|
^
|
||||||
|
SELECT 1_000.5e_1;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "1_000.5e"
|
||||||
|
LINE 1: SELECT 1_000.5e_1;
|
||||||
|
^
|
||||||
--
|
--
|
||||||
-- Test implicit type conversions
|
-- Test implicit type conversions
|
||||||
-- This fails for Postgres v6.1 (and earlier?)
|
-- This fails for Postgres v6.1 (and earlier?)
|
||||||
|
@ -1503,7 +1503,7 @@ explain (costs off) select * from like_op_noprune where a like '%BC';
|
|||||||
create table lparted_by_int2 (a smallint) partition by list (a);
|
create table lparted_by_int2 (a smallint) partition by list (a);
|
||||||
create table lparted_by_int2_1 partition of lparted_by_int2 for values in (1);
|
create table lparted_by_int2_1 partition of lparted_by_int2 for values in (1);
|
||||||
create table lparted_by_int2_16384 partition of lparted_by_int2 for values in (16384);
|
create table lparted_by_int2_16384 partition of lparted_by_int2 for values in (16384);
|
||||||
explain (costs off) select * from lparted_by_int2 where a = 100000000000000;
|
explain (costs off) select * from lparted_by_int2 where a = 100_000_000_000_000;
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
--------------------------
|
--------------------------
|
||||||
Result
|
Result
|
||||||
@ -1514,7 +1514,7 @@ create table rparted_by_int2 (a smallint) partition by range (a);
|
|||||||
create table rparted_by_int2_1 partition of rparted_by_int2 for values from (1) to (10);
|
create table rparted_by_int2_1 partition of rparted_by_int2 for values from (1) to (10);
|
||||||
create table rparted_by_int2_16384 partition of rparted_by_int2 for values from (10) to (16384);
|
create table rparted_by_int2_16384 partition of rparted_by_int2 for values from (10) to (16384);
|
||||||
-- all partitions pruned
|
-- all partitions pruned
|
||||||
explain (costs off) select * from rparted_by_int2 where a > 100000000000000;
|
explain (costs off) select * from rparted_by_int2 where a > 100_000_000_000_000;
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
--------------------------
|
--------------------------
|
||||||
Result
|
Result
|
||||||
@ -1523,7 +1523,7 @@ explain (costs off) select * from rparted_by_int2 where a > 100000000000000;
|
|||||||
|
|
||||||
create table rparted_by_int2_maxvalue partition of rparted_by_int2 for values from (16384) to (maxvalue);
|
create table rparted_by_int2_maxvalue partition of rparted_by_int2 for values from (16384) to (maxvalue);
|
||||||
-- all partitions but rparted_by_int2_maxvalue pruned
|
-- all partitions but rparted_by_int2_maxvalue pruned
|
||||||
explain (costs off) select * from rparted_by_int2 where a > 100000000000000;
|
explain (costs off) select * from rparted_by_int2 where a > 100_000_000_000_000;
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
Seq Scan on rparted_by_int2_maxvalue rparted_by_int2
|
Seq Scan on rparted_by_int2_maxvalue rparted_by_int2
|
||||||
|
@ -141,3 +141,17 @@ SELECT int2 '-0o100000';
|
|||||||
SELECT int2 '-0o100001';
|
SELECT int2 '-0o100001';
|
||||||
SELECT int2 '-0x8000';
|
SELECT int2 '-0x8000';
|
||||||
SELECT int2 '-0x8001';
|
SELECT int2 '-0x8001';
|
||||||
|
|
||||||
|
|
||||||
|
-- underscores
|
||||||
|
|
||||||
|
SELECT int2 '1_000';
|
||||||
|
SELECT int2 '1_2_3';
|
||||||
|
SELECT int2 '0xE_FF';
|
||||||
|
SELECT int2 '0o2_73';
|
||||||
|
SELECT int2 '0b_10_0101';
|
||||||
|
|
||||||
|
-- error cases
|
||||||
|
SELECT int2 '_100';
|
||||||
|
SELECT int2 '100_';
|
||||||
|
SELECT int2 '10__000';
|
||||||
|
@ -196,3 +196,17 @@ SELECT int4 '-0o20000000000';
|
|||||||
SELECT int4 '-0o20000000001';
|
SELECT int4 '-0o20000000001';
|
||||||
SELECT int4 '-0x80000000';
|
SELECT int4 '-0x80000000';
|
||||||
SELECT int4 '-0x80000001';
|
SELECT int4 '-0x80000001';
|
||||||
|
|
||||||
|
|
||||||
|
-- underscores
|
||||||
|
|
||||||
|
SELECT int4 '1_000_000';
|
||||||
|
SELECT int4 '1_2_3';
|
||||||
|
SELECT int4 '0x1EEE_FFFF';
|
||||||
|
SELECT int4 '0o2_73';
|
||||||
|
SELECT int4 '0b_10_0101';
|
||||||
|
|
||||||
|
-- error cases
|
||||||
|
SELECT int4 '_100';
|
||||||
|
SELECT int4 '100_';
|
||||||
|
SELECT int4 '100__000';
|
||||||
|
@ -277,3 +277,17 @@ SELECT int8 '-0o1000000000000000000000';
|
|||||||
SELECT int8 '-0o1000000000000000000001';
|
SELECT int8 '-0o1000000000000000000001';
|
||||||
SELECT int8 '-0x8000000000000000';
|
SELECT int8 '-0x8000000000000000';
|
||||||
SELECT int8 '-0x8000000000000001';
|
SELECT int8 '-0x8000000000000001';
|
||||||
|
|
||||||
|
|
||||||
|
-- underscores
|
||||||
|
|
||||||
|
SELECT int8 '1_000_000';
|
||||||
|
SELECT int8 '1_2_3';
|
||||||
|
SELECT int8 '0x1EEE_FFFF';
|
||||||
|
SELECT int8 '0o2_73';
|
||||||
|
SELECT int8 '0b_10_0101';
|
||||||
|
|
||||||
|
-- error cases
|
||||||
|
SELECT int8 '_100';
|
||||||
|
SELECT int8 '100_';
|
||||||
|
SELECT int8 '100__000';
|
||||||
|
@ -1039,12 +1039,17 @@ INSERT INTO num_input_test(n1) VALUES (' -inf ');
|
|||||||
INSERT INTO num_input_test(n1) VALUES (' Infinity ');
|
INSERT INTO num_input_test(n1) VALUES (' Infinity ');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' +inFinity ');
|
INSERT INTO num_input_test(n1) VALUES (' +inFinity ');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' -INFINITY ');
|
INSERT INTO num_input_test(n1) VALUES (' -INFINITY ');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('12_000_000_000');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('12_000.123_456');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('23_000_000_000e-1_0');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('.000_000_000_123e1_0');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('.000_000_000_123e+1_1');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('0b10001110111100111100001001010');
|
INSERT INTO num_input_test(n1) VALUES ('0b10001110111100111100001001010');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' -0B1010101101010100101010011000110011101011000111110000101011010010 ');
|
INSERT INTO num_input_test(n1) VALUES (' -0B_1010_1011_0101_0100_1010_1001_1000_1100_1110_1011_0001_1111_0000_1010_1101_0010 ');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' +0o112402761777 ');
|
INSERT INTO num_input_test(n1) VALUES (' +0o112402761777 ');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('-0O001255245230633431670261');
|
INSERT INTO num_input_test(n1) VALUES ('-0O0012_5524_5230_6334_3167_0261');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('-0x0000000000000000000000000deadbeef');
|
INSERT INTO num_input_test(n1) VALUES ('-0x0000000000000000000000000deadbeef');
|
||||||
INSERT INTO num_input_test(n1) VALUES (' 0X30b1F33a6DF0bD4E64DF9BdA7D15 ');
|
INSERT INTO num_input_test(n1) VALUES (' 0X_30b1_F33a_6DF0_bD4E_64DF_9BdA_7D15 ');
|
||||||
|
|
||||||
-- bad inputs
|
-- bad inputs
|
||||||
INSERT INTO num_input_test(n1) VALUES (' ');
|
INSERT INTO num_input_test(n1) VALUES (' ');
|
||||||
@ -1058,11 +1063,22 @@ INSERT INTO num_input_test(n1) VALUES (' N aN ');
|
|||||||
INSERT INTO num_input_test(n1) VALUES ('+NaN');
|
INSERT INTO num_input_test(n1) VALUES ('+NaN');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('-NaN');
|
INSERT INTO num_input_test(n1) VALUES ('-NaN');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('+ infinity');
|
INSERT INTO num_input_test(n1) VALUES ('+ infinity');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('_123');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('123_');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('12__34');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('123_.456');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('123._456');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('1.2e_34');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('1.2e34_');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('1.2e3__4');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('0b1112');
|
INSERT INTO num_input_test(n1) VALUES ('0b1112');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('0c1112');
|
INSERT INTO num_input_test(n1) VALUES ('0c1112');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('0o12345678');
|
INSERT INTO num_input_test(n1) VALUES ('0o12345678');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('0x1eg');
|
INSERT INTO num_input_test(n1) VALUES ('0x1eg');
|
||||||
INSERT INTO num_input_test(n1) VALUES ('0x12.34');
|
INSERT INTO num_input_test(n1) VALUES ('0x12.34');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('0x__1234');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('0x1234_');
|
||||||
|
INSERT INTO num_input_test(n1) VALUES ('0x12__34');
|
||||||
|
|
||||||
SELECT * FROM num_input_test;
|
SELECT * FROM num_input_test;
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ SELECT -0x8000000000000001;
|
|||||||
-- error cases
|
-- error cases
|
||||||
SELECT 123abc;
|
SELECT 123abc;
|
||||||
SELECT 0x0o;
|
SELECT 0x0o;
|
||||||
SELECT 1_2_3;
|
|
||||||
SELECT 0.a;
|
SELECT 0.a;
|
||||||
SELECT 0.0a;
|
SELECT 0.0a;
|
||||||
SELECT .0a;
|
SELECT .0a;
|
||||||
@ -66,6 +65,29 @@ SELECT 0x;
|
|||||||
SELECT 1x;
|
SELECT 1x;
|
||||||
SELECT 0x0y;
|
SELECT 0x0y;
|
||||||
|
|
||||||
|
-- underscores
|
||||||
|
SELECT 1_000_000;
|
||||||
|
SELECT 1_2_3;
|
||||||
|
SELECT 0x1EEE_FFFF;
|
||||||
|
SELECT 0o2_73;
|
||||||
|
SELECT 0b_10_0101;
|
||||||
|
|
||||||
|
SELECT 1_000.000_005;
|
||||||
|
SELECT 1_000.;
|
||||||
|
SELECT .000_005;
|
||||||
|
SELECT 1_000.5e0_1;
|
||||||
|
|
||||||
|
-- error cases
|
||||||
|
SELECT _100;
|
||||||
|
SELECT 100_;
|
||||||
|
SELECT 100__000;
|
||||||
|
|
||||||
|
SELECT _1_000.5;
|
||||||
|
SELECT 1_000_.5;
|
||||||
|
SELECT 1_000._5;
|
||||||
|
SELECT 1_000.5_;
|
||||||
|
SELECT 1_000.5e_1;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Test implicit type conversions
|
-- Test implicit type conversions
|
||||||
|
@ -283,16 +283,16 @@ explain (costs off) select * from like_op_noprune where a like '%BC';
|
|||||||
create table lparted_by_int2 (a smallint) partition by list (a);
|
create table lparted_by_int2 (a smallint) partition by list (a);
|
||||||
create table lparted_by_int2_1 partition of lparted_by_int2 for values in (1);
|
create table lparted_by_int2_1 partition of lparted_by_int2 for values in (1);
|
||||||
create table lparted_by_int2_16384 partition of lparted_by_int2 for values in (16384);
|
create table lparted_by_int2_16384 partition of lparted_by_int2 for values in (16384);
|
||||||
explain (costs off) select * from lparted_by_int2 where a = 100000000000000;
|
explain (costs off) select * from lparted_by_int2 where a = 100_000_000_000_000;
|
||||||
|
|
||||||
create table rparted_by_int2 (a smallint) partition by range (a);
|
create table rparted_by_int2 (a smallint) partition by range (a);
|
||||||
create table rparted_by_int2_1 partition of rparted_by_int2 for values from (1) to (10);
|
create table rparted_by_int2_1 partition of rparted_by_int2 for values from (1) to (10);
|
||||||
create table rparted_by_int2_16384 partition of rparted_by_int2 for values from (10) to (16384);
|
create table rparted_by_int2_16384 partition of rparted_by_int2 for values from (10) to (16384);
|
||||||
-- all partitions pruned
|
-- all partitions pruned
|
||||||
explain (costs off) select * from rparted_by_int2 where a > 100000000000000;
|
explain (costs off) select * from rparted_by_int2 where a > 100_000_000_000_000;
|
||||||
create table rparted_by_int2_maxvalue partition of rparted_by_int2 for values from (16384) to (maxvalue);
|
create table rparted_by_int2_maxvalue partition of rparted_by_int2 for values from (16384) to (maxvalue);
|
||||||
-- all partitions but rparted_by_int2_maxvalue pruned
|
-- all partitions but rparted_by_int2_maxvalue pruned
|
||||||
explain (costs off) select * from rparted_by_int2 where a > 100000000000000;
|
explain (costs off) select * from rparted_by_int2 where a > 100_000_000_000_000;
|
||||||
|
|
||||||
drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
|
drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user