mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
Non-decimal integer literals
Add support for hexadecimal, octal, and binary integer literals: 0x42F 0o273 0b100101 per SQL:202x draft. This adds support in the lexer as well as in the integer type input functions. Reviewed-by: John Naylor <john.naylor@enterprisedb.com> Reviewed-by: Zhihong Yu <zyu@yugabyte.com> Reviewed-by: David Rowley <dgrowleyml@gmail.com> Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/b239564c-cad0-b23e-c57e-166d883cb97d@enterprisedb.com
This commit is contained in:
@ -694,6 +694,40 @@ $function$
|
|||||||
</literallayout>
|
</literallayout>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Additionally, non-decimal integer constants can be used in these forms:
|
||||||
|
<synopsis>
|
||||||
|
0x<replaceable>hexdigits</replaceable>
|
||||||
|
0o<replaceable>octdigits</replaceable>
|
||||||
|
0b<replaceable>bindigits</replaceable>
|
||||||
|
</synopsis>
|
||||||
|
<replaceable>hexdigits</replaceable> is one or more hexadecimal digits
|
||||||
|
(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 or 1). Hexadecimal digits and the radix prefixes can be in
|
||||||
|
upper or lower case. Note that only integers can have non-decimal forms,
|
||||||
|
not numbers with fractional parts.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
These are some examples of this:
|
||||||
|
<literallayout>0b100101
|
||||||
|
0B10011001
|
||||||
|
0o273
|
||||||
|
0O755
|
||||||
|
0x42f
|
||||||
|
0XFFFF
|
||||||
|
</literallayout>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Nondecimal integer constants are currently only supported in the range
|
||||||
|
of the <type>bigint</type> type (see <xref
|
||||||
|
linkend="datatype-numeric-table"/>).
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<indexterm><primary>integer</primary></indexterm>
|
<indexterm><primary>integer</primary></indexterm>
|
||||||
<indexterm><primary>bigint</primary></indexterm>
|
<indexterm><primary>bigint</primary></indexterm>
|
||||||
|
@ -119,7 +119,7 @@ RETURN
|
|||||||
WHEN 1700 /*numeric*/ THEN
|
WHEN 1700 /*numeric*/ THEN
|
||||||
CASE WHEN $2 = -1
|
CASE WHEN $2 = -1
|
||||||
THEN null
|
THEN null
|
||||||
ELSE (($2 - 4) >> 16) & 65535
|
ELSE (($2 - 4) >> 16) & 0xFFFF
|
||||||
END
|
END
|
||||||
WHEN 700 /*float4*/ THEN 24 /*FLT_MANT_DIG*/
|
WHEN 700 /*float4*/ THEN 24 /*FLT_MANT_DIG*/
|
||||||
WHEN 701 /*float8*/ THEN 53 /*DBL_MANT_DIG*/
|
WHEN 701 /*float8*/ THEN 53 /*DBL_MANT_DIG*/
|
||||||
@ -147,7 +147,7 @@ RETURN
|
|||||||
WHEN $1 IN (1700) THEN
|
WHEN $1 IN (1700) THEN
|
||||||
CASE WHEN $2 = -1
|
CASE WHEN $2 = -1
|
||||||
THEN null
|
THEN null
|
||||||
ELSE ($2 - 4) & 65535
|
ELSE ($2 - 4) & 0xFFFF
|
||||||
END
|
END
|
||||||
ELSE null
|
ELSE null
|
||||||
END;
|
END;
|
||||||
@ -163,7 +163,7 @@ RETURN
|
|||||||
WHEN $1 IN (1083, 1114, 1184, 1266) /* time, timestamp, same + tz */
|
WHEN $1 IN (1083, 1114, 1184, 1266) /* time, timestamp, same + tz */
|
||||||
THEN CASE WHEN $2 < 0 THEN 6 ELSE $2 END
|
THEN CASE WHEN $2 < 0 THEN 6 ELSE $2 END
|
||||||
WHEN $1 IN (1186) /* interval */
|
WHEN $1 IN (1186) /* interval */
|
||||||
THEN CASE WHEN $2 < 0 OR $2 & 65535 = 65535 THEN 6 ELSE $2 & 65535 END
|
THEN CASE WHEN $2 < 0 OR $2 & 0xFFFF = 0xFFFF THEN 6 ELSE $2 & 0xFFFF END
|
||||||
ELSE null
|
ELSE null
|
||||||
END;
|
END;
|
||||||
|
|
||||||
|
@ -527,6 +527,7 @@ T652 SQL-dynamic statements in SQL routines NO
|
|||||||
T653 SQL-schema statements in external routines YES
|
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
|
||||||
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
|
||||||
|
@ -385,11 +385,46 @@ 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;
|
||||||
|
char *startptr;
|
||||||
|
int sign;
|
||||||
|
char *testvalue;
|
||||||
int64 val64;
|
int64 val64;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
|
startptr = aconst->val.fval.fval;
|
||||||
|
if (startptr[0] == '-')
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (startptr[1] == 'x' || startptr[1] == 'X')
|
||||||
|
{
|
||||||
|
base = 16;
|
||||||
|
startptr += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign == +1)
|
||||||
|
testvalue = startptr;
|
||||||
|
else
|
||||||
|
testvalue = psprintf("-%s", startptr);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
val64 = strtoi64(aconst->val.fval.fval, &endptr, 10);
|
val64 = strtoi64(testvalue, &endptr, base);
|
||||||
if (errno == 0 && *endptr == '\0')
|
if (errno == 0 && *endptr == '\0')
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -124,7 +124,7 @@ static void addlit(char *ytext, int yleng, core_yyscan_t yyscanner);
|
|||||||
static void addlitchar(unsigned char ychar, core_yyscan_t yyscanner);
|
static void addlitchar(unsigned char ychar, core_yyscan_t yyscanner);
|
||||||
static char *litbufdup(core_yyscan_t yyscanner);
|
static char *litbufdup(core_yyscan_t yyscanner);
|
||||||
static unsigned char unescape_single_char(unsigned char c, core_yyscan_t yyscanner);
|
static unsigned char unescape_single_char(unsigned char c, core_yyscan_t yyscanner);
|
||||||
static int process_integer_literal(const char *token, YYSTYPE *lval);
|
static int process_integer_literal(const char *token, YYSTYPE *lval, int base);
|
||||||
static void addunicode(pg_wchar c, yyscan_t yyscanner);
|
static void addunicode(pg_wchar c, yyscan_t yyscanner);
|
||||||
|
|
||||||
#define yyerror(msg) scanner_yyerror(msg, yyscanner)
|
#define yyerror(msg) scanner_yyerror(msg, yyscanner)
|
||||||
@ -385,25 +385,40 @@ operator {op_chars}+
|
|||||||
* Unary minus is not part of a number here. Instead we pass it separately to
|
* Unary minus is not part of a number here. Instead we pass it separately to
|
||||||
* the parser, and there it gets coerced via doNegate().
|
* the parser, and there it gets coerced via doNegate().
|
||||||
*
|
*
|
||||||
* {decimalfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
|
* {numericfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
|
||||||
*
|
*
|
||||||
* {realfail} is added to prevent the need for scanner
|
* {realfail} is added to prevent the need for scanner
|
||||||
* backup when the {real} rule fails to match completely.
|
* backup when the {real} rule fails to match completely.
|
||||||
*/
|
*/
|
||||||
digit [0-9]
|
decdigit [0-9]
|
||||||
|
hexdigit [0-9A-Fa-f]
|
||||||
|
octdigit [0-7]
|
||||||
|
bindigit [0-1]
|
||||||
|
|
||||||
integer {digit}+
|
decinteger {decdigit}+
|
||||||
decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))
|
hexinteger 0[xX]{hexdigit}+
|
||||||
decimalfail {digit}+\.\.
|
octinteger 0[oO]{octdigit}+
|
||||||
real ({integer}|{decimal})[Ee][-+]?{digit}+
|
bininteger 0[bB]{bindigit}+
|
||||||
realfail ({integer}|{decimal})[Ee][-+]
|
|
||||||
|
|
||||||
integer_junk {integer}{ident_start}
|
hexfail 0[xX]
|
||||||
decimal_junk {decimal}{ident_start}
|
octfail 0[oO]
|
||||||
|
binfail 0[bB]
|
||||||
|
|
||||||
|
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
|
||||||
|
numericfail {decdigit}+\.\.
|
||||||
|
|
||||||
|
real ({decinteger}|{numeric})[Ee][-+]?{decdigit}+
|
||||||
|
realfail ({decinteger}|{numeric})[Ee][-+]
|
||||||
|
|
||||||
|
decinteger_junk {decinteger}{ident_start}
|
||||||
|
hexinteger_junk {hexinteger}{ident_start}
|
||||||
|
octinteger_junk {octinteger}{ident_start}
|
||||||
|
bininteger_junk {bininteger}{ident_start}
|
||||||
|
numeric_junk {numeric}{ident_start}
|
||||||
real_junk {real}{ident_start}
|
real_junk {real}{ident_start}
|
||||||
|
|
||||||
param \${integer}
|
param \${decinteger}
|
||||||
param_junk \${integer}{ident_start}
|
param_junk \${decinteger}{ident_start}
|
||||||
|
|
||||||
other .
|
other .
|
||||||
|
|
||||||
@ -983,20 +998,44 @@ other .
|
|||||||
yyerror("trailing junk after parameter");
|
yyerror("trailing junk after parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
{integer} {
|
{decinteger} {
|
||||||
SET_YYLLOC();
|
SET_YYLLOC();
|
||||||
return process_integer_literal(yytext, yylval);
|
return process_integer_literal(yytext, yylval, 10);
|
||||||
}
|
}
|
||||||
{decimal} {
|
{hexinteger} {
|
||||||
|
SET_YYLLOC();
|
||||||
|
return process_integer_literal(yytext, yylval, 16);
|
||||||
|
}
|
||||||
|
{octinteger} {
|
||||||
|
SET_YYLLOC();
|
||||||
|
return process_integer_literal(yytext, yylval, 8);
|
||||||
|
}
|
||||||
|
{bininteger} {
|
||||||
|
SET_YYLLOC();
|
||||||
|
return process_integer_literal(yytext, yylval, 2);
|
||||||
|
}
|
||||||
|
{hexfail} {
|
||||||
|
SET_YYLLOC();
|
||||||
|
yyerror("invalid hexadecimal integer");
|
||||||
|
}
|
||||||
|
{octfail} {
|
||||||
|
SET_YYLLOC();
|
||||||
|
yyerror("invalid octal integer");
|
||||||
|
}
|
||||||
|
{binfail} {
|
||||||
|
SET_YYLLOC();
|
||||||
|
yyerror("invalid binary integer");
|
||||||
|
}
|
||||||
|
{numeric} {
|
||||||
SET_YYLLOC();
|
SET_YYLLOC();
|
||||||
yylval->str = pstrdup(yytext);
|
yylval->str = pstrdup(yytext);
|
||||||
return FCONST;
|
return FCONST;
|
||||||
}
|
}
|
||||||
{decimalfail} {
|
{numericfail} {
|
||||||
/* throw back the .., and treat as integer */
|
/* throw back the .., and treat as integer */
|
||||||
yyless(yyleng - 2);
|
yyless(yyleng - 2);
|
||||||
SET_YYLLOC();
|
SET_YYLLOC();
|
||||||
return process_integer_literal(yytext, yylval);
|
return process_integer_literal(yytext, yylval, 10);
|
||||||
}
|
}
|
||||||
{real} {
|
{real} {
|
||||||
SET_YYLLOC();
|
SET_YYLLOC();
|
||||||
@ -1007,11 +1046,23 @@ other .
|
|||||||
SET_YYLLOC();
|
SET_YYLLOC();
|
||||||
yyerror("trailing junk after numeric literal");
|
yyerror("trailing junk after numeric literal");
|
||||||
}
|
}
|
||||||
{integer_junk} {
|
{decinteger_junk} {
|
||||||
SET_YYLLOC();
|
SET_YYLLOC();
|
||||||
yyerror("trailing junk after numeric literal");
|
yyerror("trailing junk after numeric literal");
|
||||||
}
|
}
|
||||||
{decimal_junk} {
|
{hexinteger_junk} {
|
||||||
|
SET_YYLLOC();
|
||||||
|
yyerror("trailing junk after numeric literal");
|
||||||
|
}
|
||||||
|
{octinteger_junk} {
|
||||||
|
SET_YYLLOC();
|
||||||
|
yyerror("trailing junk after numeric literal");
|
||||||
|
}
|
||||||
|
{bininteger_junk} {
|
||||||
|
SET_YYLLOC();
|
||||||
|
yyerror("trailing junk after numeric literal");
|
||||||
|
}
|
||||||
|
{numeric_junk} {
|
||||||
SET_YYLLOC();
|
SET_YYLLOC();
|
||||||
yyerror("trailing junk after numeric literal");
|
yyerror("trailing junk after numeric literal");
|
||||||
}
|
}
|
||||||
@ -1307,17 +1358,17 @@ litbufdup(core_yyscan_t yyscanner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process {integer}. Note this will also do the right thing with {decimal},
|
* Process {decinteger}, {hexinteger}, etc. Note this will also do the right
|
||||||
* ie digits and a decimal point.
|
* thing with {numeric}, ie digits and a decimal point.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
process_integer_literal(const char *token, YYSTYPE *lval)
|
process_integer_literal(const char *token, YYSTYPE *lval, int base)
|
||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
val = strtoint(token, &endptr, 10);
|
val = strtoint(base == 10 ? token : token + 2, &endptr, base);
|
||||||
if (*endptr != '\0' || errno == ERANGE)
|
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 */
|
||||||
|
@ -85,6 +85,17 @@ decimalLength64(const uint64 v)
|
|||||||
return t + (v >= PowersOfTen[t]);
|
return t + (v >= PowersOfTen[t]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const int8 hexlookup[128] = {
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert input string to a signed 16 bit integer.
|
* Convert input string to a signed 16 bit integer.
|
||||||
*
|
*
|
||||||
@ -108,6 +119,7 @@ int16
|
|||||||
pg_strtoint16_safe(const char *s, Node *escontext)
|
pg_strtoint16_safe(const char *s, Node *escontext)
|
||||||
{
|
{
|
||||||
const char *ptr = s;
|
const char *ptr = s;
|
||||||
|
const char *firstdigit;
|
||||||
uint16 tmp = 0;
|
uint16 tmp = 0;
|
||||||
bool neg = false;
|
bool neg = false;
|
||||||
|
|
||||||
@ -124,11 +136,47 @@ pg_strtoint16_safe(const char *s, Node *escontext)
|
|||||||
else if (*ptr == '+')
|
else if (*ptr == '+')
|
||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
/* require at least one digit */
|
|
||||||
if (unlikely(!isdigit((unsigned char) *ptr)))
|
|
||||||
goto invalid_syntax;
|
|
||||||
|
|
||||||
/* process digits */
|
/* process digits */
|
||||||
|
if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
|
||||||
|
{
|
||||||
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
|
while (*ptr && isxdigit((unsigned char) *ptr))
|
||||||
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT16_MIN / 16)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
|
tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
|
||||||
|
{
|
||||||
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
|
while (*ptr && (*ptr >= '0' && *ptr <= '7'))
|
||||||
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT16_MIN / 8)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
|
tmp = tmp * 8 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
|
||||||
|
{
|
||||||
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
|
while (*ptr && (*ptr >= '0' && *ptr <= '1'))
|
||||||
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT16_MIN / 2)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
|
tmp = tmp * 2 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstdigit = ptr;
|
||||||
|
|
||||||
while (*ptr && isdigit((unsigned char) *ptr))
|
while (*ptr && isdigit((unsigned char) *ptr))
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT16_MIN / 10)))
|
if (unlikely(tmp > -(PG_INT16_MIN / 10)))
|
||||||
@ -136,6 +184,11 @@ pg_strtoint16_safe(const char *s, Node *escontext)
|
|||||||
|
|
||||||
tmp = tmp * 10 + (*ptr++ - '0');
|
tmp = tmp * 10 + (*ptr++ - '0');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* require at least one digit */
|
||||||
|
if (unlikely(ptr == firstdigit))
|
||||||
|
goto invalid_syntax;
|
||||||
|
|
||||||
/* allow trailing whitespace, but not other trailing chars */
|
/* allow trailing whitespace, but not other trailing chars */
|
||||||
while (*ptr != '\0' && isspace((unsigned char) *ptr))
|
while (*ptr != '\0' && isspace((unsigned char) *ptr))
|
||||||
@ -193,6 +246,7 @@ int32
|
|||||||
pg_strtoint32_safe(const char *s, Node *escontext)
|
pg_strtoint32_safe(const char *s, Node *escontext)
|
||||||
{
|
{
|
||||||
const char *ptr = s;
|
const char *ptr = s;
|
||||||
|
const char *firstdigit;
|
||||||
uint32 tmp = 0;
|
uint32 tmp = 0;
|
||||||
bool neg = false;
|
bool neg = false;
|
||||||
|
|
||||||
@ -209,11 +263,47 @@ pg_strtoint32_safe(const char *s, Node *escontext)
|
|||||||
else if (*ptr == '+')
|
else if (*ptr == '+')
|
||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
/* require at least one digit */
|
|
||||||
if (unlikely(!isdigit((unsigned char) *ptr)))
|
|
||||||
goto invalid_syntax;
|
|
||||||
|
|
||||||
/* process digits */
|
/* process digits */
|
||||||
|
if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
|
||||||
|
{
|
||||||
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
|
while (*ptr && isxdigit((unsigned char) *ptr))
|
||||||
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT32_MIN / 16)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
|
tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
|
||||||
|
{
|
||||||
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
|
while (*ptr && (*ptr >= '0' && *ptr <= '7'))
|
||||||
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT32_MIN / 8)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
|
tmp = tmp * 8 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
|
||||||
|
{
|
||||||
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
|
while (*ptr && (*ptr >= '0' && *ptr <= '1'))
|
||||||
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT32_MIN / 2)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
|
tmp = tmp * 2 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstdigit = ptr;
|
||||||
|
|
||||||
while (*ptr && isdigit((unsigned char) *ptr))
|
while (*ptr && isdigit((unsigned char) *ptr))
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT32_MIN / 10)))
|
if (unlikely(tmp > -(PG_INT32_MIN / 10)))
|
||||||
@ -221,6 +311,11 @@ pg_strtoint32_safe(const char *s, Node *escontext)
|
|||||||
|
|
||||||
tmp = tmp * 10 + (*ptr++ - '0');
|
tmp = tmp * 10 + (*ptr++ - '0');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* require at least one digit */
|
||||||
|
if (unlikely(ptr == firstdigit))
|
||||||
|
goto invalid_syntax;
|
||||||
|
|
||||||
/* allow trailing whitespace, but not other trailing chars */
|
/* allow trailing whitespace, but not other trailing chars */
|
||||||
while (*ptr != '\0' && isspace((unsigned char) *ptr))
|
while (*ptr != '\0' && isspace((unsigned char) *ptr))
|
||||||
@ -278,6 +373,7 @@ int64
|
|||||||
pg_strtoint64_safe(const char *s, Node *escontext)
|
pg_strtoint64_safe(const char *s, Node *escontext)
|
||||||
{
|
{
|
||||||
const char *ptr = s;
|
const char *ptr = s;
|
||||||
|
const char *firstdigit;
|
||||||
uint64 tmp = 0;
|
uint64 tmp = 0;
|
||||||
bool neg = false;
|
bool neg = false;
|
||||||
|
|
||||||
@ -294,11 +390,47 @@ pg_strtoint64_safe(const char *s, Node *escontext)
|
|||||||
else if (*ptr == '+')
|
else if (*ptr == '+')
|
||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
/* require at least one digit */
|
|
||||||
if (unlikely(!isdigit((unsigned char) *ptr)))
|
|
||||||
goto invalid_syntax;
|
|
||||||
|
|
||||||
/* process digits */
|
/* process digits */
|
||||||
|
if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
|
||||||
|
{
|
||||||
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
|
while (*ptr && isxdigit((unsigned char) *ptr))
|
||||||
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT64_MIN / 16)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
|
tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
|
||||||
|
{
|
||||||
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
|
while (*ptr && (*ptr >= '0' && *ptr <= '7'))
|
||||||
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT64_MIN / 8)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
|
tmp = tmp * 8 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
|
||||||
|
{
|
||||||
|
firstdigit = ptr += 2;
|
||||||
|
|
||||||
|
while (*ptr && (*ptr >= '0' && *ptr <= '1'))
|
||||||
|
{
|
||||||
|
if (unlikely(tmp > -(PG_INT64_MIN / 2)))
|
||||||
|
goto out_of_range;
|
||||||
|
|
||||||
|
tmp = tmp * 2 + (*ptr++ - '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstdigit = ptr;
|
||||||
|
|
||||||
while (*ptr && isdigit((unsigned char) *ptr))
|
while (*ptr && isdigit((unsigned char) *ptr))
|
||||||
{
|
{
|
||||||
if (unlikely(tmp > -(PG_INT64_MIN / 10)))
|
if (unlikely(tmp > -(PG_INT64_MIN / 10)))
|
||||||
@ -306,6 +438,11 @@ pg_strtoint64_safe(const char *s, Node *escontext)
|
|||||||
|
|
||||||
tmp = tmp * 10 + (*ptr++ - '0');
|
tmp = tmp * 10 + (*ptr++ - '0');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* require at least one digit */
|
||||||
|
if (unlikely(ptr == firstdigit))
|
||||||
|
goto invalid_syntax;
|
||||||
|
|
||||||
/* allow trailing whitespace, but not other trailing chars */
|
/* allow trailing whitespace, but not other trailing chars */
|
||||||
while (*ptr != '\0' && isspace((unsigned char) *ptr))
|
while (*ptr != '\0' && isspace((unsigned char) *ptr))
|
||||||
|
@ -323,25 +323,40 @@ operator {op_chars}+
|
|||||||
* Unary minus is not part of a number here. Instead we pass it separately to
|
* Unary minus is not part of a number here. Instead we pass it separately to
|
||||||
* the parser, and there it gets coerced via doNegate().
|
* the parser, and there it gets coerced via doNegate().
|
||||||
*
|
*
|
||||||
* {decimalfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
|
* {numericfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
|
||||||
*
|
*
|
||||||
* {realfail} is added to prevent the need for scanner
|
* {realfail} is added to prevent the need for scanner
|
||||||
* backup when the {real} rule fails to match completely.
|
* backup when the {real} rule fails to match completely.
|
||||||
*/
|
*/
|
||||||
digit [0-9]
|
decdigit [0-9]
|
||||||
|
hexdigit [0-9A-Fa-f]
|
||||||
|
octdigit [0-7]
|
||||||
|
bindigit [0-1]
|
||||||
|
|
||||||
integer {digit}+
|
decinteger {decdigit}+
|
||||||
decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))
|
hexinteger 0[xX]{hexdigit}+
|
||||||
decimalfail {digit}+\.\.
|
octinteger 0[oO]{octdigit}+
|
||||||
real ({integer}|{decimal})[Ee][-+]?{digit}+
|
bininteger 0[bB]{bindigit}+
|
||||||
realfail ({integer}|{decimal})[Ee][-+]
|
|
||||||
|
|
||||||
integer_junk {integer}{ident_start}
|
hexfail 0[xX]
|
||||||
decimal_junk {decimal}{ident_start}
|
octfail 0[oO]
|
||||||
|
binfail 0[bB]
|
||||||
|
|
||||||
|
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
|
||||||
|
numericfail {decdigit}+\.\.
|
||||||
|
|
||||||
|
real ({decinteger}|{numeric})[Ee][-+]?{decdigit}+
|
||||||
|
realfail ({decinteger}|{numeric})[Ee][-+]
|
||||||
|
|
||||||
|
decinteger_junk {decinteger}{ident_start}
|
||||||
|
hexinteger_junk {hexinteger}{ident_start}
|
||||||
|
octinteger_junk {octinteger}{ident_start}
|
||||||
|
bininteger_junk {bininteger}{ident_start}
|
||||||
|
numeric_junk {numeric}{ident_start}
|
||||||
real_junk {real}{ident_start}
|
real_junk {real}{ident_start}
|
||||||
|
|
||||||
param \${integer}
|
param \${decinteger}
|
||||||
param_junk \${integer}{ident_start}
|
param_junk \${decinteger}{ident_start}
|
||||||
|
|
||||||
/* psql-specific: characters allowed in variable names */
|
/* psql-specific: characters allowed in variable names */
|
||||||
variable_char [A-Za-z\200-\377_0-9]
|
variable_char [A-Za-z\200-\377_0-9]
|
||||||
@ -847,13 +862,31 @@ other .
|
|||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
|
|
||||||
{integer} {
|
{decinteger} {
|
||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
{decimal} {
|
{hexinteger} {
|
||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
{decimalfail} {
|
{octinteger} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
{bininteger} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
{hexfail} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
{octfail} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
{binfail} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
{numeric} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
{numericfail} {
|
||||||
/* throw back the .., and treat as integer */
|
/* throw back the .., and treat as integer */
|
||||||
yyless(yyleng - 2);
|
yyless(yyleng - 2);
|
||||||
ECHO;
|
ECHO;
|
||||||
@ -864,10 +897,19 @@ other .
|
|||||||
{realfail} {
|
{realfail} {
|
||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
{integer_junk} {
|
{decinteger_junk} {
|
||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
{decimal_junk} {
|
{hexinteger_junk} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
{octinteger_junk} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
{bininteger_junk} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
{numeric_junk} {
|
||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
{real_junk} {
|
{real_junk} {
|
||||||
|
@ -57,7 +57,7 @@ static bool include_next;
|
|||||||
#define startlit() (literalbuf[0] = '\0', literallen = 0)
|
#define startlit() (literalbuf[0] = '\0', literallen = 0)
|
||||||
static void addlit(char *ytext, int yleng);
|
static void addlit(char *ytext, int yleng);
|
||||||
static void addlitchar(unsigned char ychar);
|
static void addlitchar(unsigned char ychar);
|
||||||
static int process_integer_literal(const char *token, YYSTYPE *lval);
|
static int process_integer_literal(const char *token, YYSTYPE *lval, int base);
|
||||||
static void parse_include(void);
|
static void parse_include(void);
|
||||||
static bool ecpg_isspace(char ch);
|
static bool ecpg_isspace(char ch);
|
||||||
static bool isdefine(void);
|
static bool isdefine(void);
|
||||||
@ -351,25 +351,40 @@ operator {op_chars}+
|
|||||||
* Unary minus is not part of a number here. Instead we pass it separately to
|
* Unary minus is not part of a number here. Instead we pass it separately to
|
||||||
* the parser, and there it gets coerced via doNegate().
|
* the parser, and there it gets coerced via doNegate().
|
||||||
*
|
*
|
||||||
* {decimalfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
|
* {numericfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
|
||||||
*
|
*
|
||||||
* {realfail} is added to prevent the need for scanner
|
* {realfail} is added to prevent the need for scanner
|
||||||
* backup when the {real} rule fails to match completely.
|
* backup when the {real} rule fails to match completely.
|
||||||
*/
|
*/
|
||||||
digit [0-9]
|
decdigit [0-9]
|
||||||
|
hexdigit [0-9A-Fa-f]
|
||||||
|
octdigit [0-7]
|
||||||
|
bindigit [0-1]
|
||||||
|
|
||||||
integer {digit}+
|
decinteger {decdigit}+
|
||||||
decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))
|
hexinteger 0[xX]{hexdigit}+
|
||||||
decimalfail {digit}+\.\.
|
octinteger 0[oO]{octdigit}+
|
||||||
real ({integer}|{decimal})[Ee][-+]?{digit}+
|
bininteger 0[bB]{bindigit}+
|
||||||
realfail ({integer}|{decimal})[Ee][-+]
|
|
||||||
|
|
||||||
integer_junk {integer}{ident_start}
|
hexfail 0[xX]
|
||||||
decimal_junk {decimal}{ident_start}
|
octfail 0[oO]
|
||||||
|
binfail 0[bB]
|
||||||
|
|
||||||
|
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
|
||||||
|
numericfail {decdigit}+\.\.
|
||||||
|
|
||||||
|
real ({decinteger}|{numeric})[Ee][-+]?{decdigit}+
|
||||||
|
realfail ({decinteger}|{numeric})[Ee][-+]
|
||||||
|
|
||||||
|
decinteger_junk {decinteger}{ident_start}
|
||||||
|
hexinteger_junk {hexinteger}{ident_start}
|
||||||
|
octinteger_junk {octinteger}{ident_start}
|
||||||
|
bininteger_junk {bininteger}{ident_start}
|
||||||
|
numeric_junk {numeric}{ident_start}
|
||||||
real_junk {real}{ident_start}
|
real_junk {real}{ident_start}
|
||||||
|
|
||||||
param \${integer}
|
param \${decinteger}
|
||||||
param_junk \${integer}{ident_start}
|
param_junk \${decinteger}{ident_start}
|
||||||
|
|
||||||
/* special characters for other dbms */
|
/* special characters for other dbms */
|
||||||
/* we have to react differently in compat mode */
|
/* we have to react differently in compat mode */
|
||||||
@ -399,9 +414,6 @@ include_next [iI][nN][cC][lL][uU][dD][eE]_[nN][eE][xX][tT]
|
|||||||
import [iI][mM][pP][oO][rR][tT]
|
import [iI][mM][pP][oO][rR][tT]
|
||||||
undef [uU][nN][dD][eE][fF]
|
undef [uU][nN][dD][eE][fF]
|
||||||
|
|
||||||
/* C version of hex number */
|
|
||||||
xch 0[xX][0-9A-Fa-f]*
|
|
||||||
|
|
||||||
ccomment "//".*\n
|
ccomment "//".*\n
|
||||||
|
|
||||||
if [iI][fF]
|
if [iI][fF]
|
||||||
@ -414,7 +426,7 @@ endif [eE][nN][dD][iI][fF]
|
|||||||
struct [sS][tT][rR][uU][cC][tT]
|
struct [sS][tT][rR][uU][cC][tT]
|
||||||
|
|
||||||
exec_sql {exec}{space}*{sql}{space}*
|
exec_sql {exec}{space}*{sql}{space}*
|
||||||
ipdigit ({digit}|{digit}{digit}|{digit}{digit}{digit})
|
ipdigit ({decdigit}|{decdigit}{decdigit}|{decdigit}{decdigit}{decdigit})
|
||||||
ip {ipdigit}\.{ipdigit}\.{ipdigit}\.{ipdigit}
|
ip {ipdigit}\.{ipdigit}\.{ipdigit}\.{ipdigit}
|
||||||
|
|
||||||
/* we might want to parse all cpp include files */
|
/* we might want to parse all cpp include files */
|
||||||
@ -932,17 +944,20 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
} /* <SQL> */
|
} /* <SQL> */
|
||||||
|
|
||||||
<C,SQL>{
|
<C,SQL>{
|
||||||
{integer} {
|
{decinteger} {
|
||||||
return process_integer_literal(yytext, &base_yylval);
|
return process_integer_literal(yytext, &base_yylval, 10);
|
||||||
}
|
}
|
||||||
{decimal} {
|
{hexinteger} {
|
||||||
|
return process_integer_literal(yytext, &base_yylval, 16);
|
||||||
|
}
|
||||||
|
{numeric} {
|
||||||
base_yylval.str = mm_strdup(yytext);
|
base_yylval.str = mm_strdup(yytext);
|
||||||
return FCONST;
|
return FCONST;
|
||||||
}
|
}
|
||||||
{decimalfail} {
|
{numericfail} {
|
||||||
/* throw back the .., and treat as integer */
|
/* throw back the .., and treat as integer */
|
||||||
yyless(yyleng - 2);
|
yyless(yyleng - 2);
|
||||||
return process_integer_literal(yytext, &base_yylval);
|
return process_integer_literal(yytext, &base_yylval, 10);
|
||||||
}
|
}
|
||||||
{real} {
|
{real} {
|
||||||
base_yylval.str = mm_strdup(yytext);
|
base_yylval.str = mm_strdup(yytext);
|
||||||
@ -951,22 +966,38 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
{realfail} {
|
{realfail} {
|
||||||
/*
|
/*
|
||||||
* throw back the [Ee][+-], and figure out whether what
|
* throw back the [Ee][+-], and figure out whether what
|
||||||
* remains is an {integer} or {decimal}.
|
* remains is an {decinteger} or {numeric}.
|
||||||
*/
|
*/
|
||||||
yyless(yyleng - 2);
|
yyless(yyleng - 2);
|
||||||
return process_integer_literal(yytext, &base_yylval);
|
return process_integer_literal(yytext, &base_yylval, 10);
|
||||||
}
|
}
|
||||||
} /* <C,SQL> */
|
} /* <C,SQL> */
|
||||||
|
|
||||||
<SQL>{
|
<SQL>{
|
||||||
|
{octinteger} {
|
||||||
|
return process_integer_literal(yytext, &base_yylval, 8);
|
||||||
|
}
|
||||||
|
{bininteger} {
|
||||||
|
return process_integer_literal(yytext, &base_yylval, 2);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that some trailing junk is valid in C (such as 100LL), so we
|
* Note that some trailing junk is valid in C (such as 100LL), so we
|
||||||
* contain this to SQL mode.
|
* contain this to SQL mode.
|
||||||
*/
|
*/
|
||||||
{integer_junk} {
|
{decinteger_junk} {
|
||||||
mmfatal(PARSE_ERROR, "trailing junk after numeric literal");
|
mmfatal(PARSE_ERROR, "trailing junk after numeric literal");
|
||||||
}
|
}
|
||||||
{decimal_junk} {
|
{hexinteger_junk} {
|
||||||
|
mmfatal(PARSE_ERROR, "trailing junk after numeric literal");
|
||||||
|
}
|
||||||
|
{octinteger_junk} {
|
||||||
|
mmfatal(PARSE_ERROR, "trailing junk after numeric literal");
|
||||||
|
}
|
||||||
|
{bininteger_junk} {
|
||||||
|
mmfatal(PARSE_ERROR, "trailing junk after numeric literal");
|
||||||
|
}
|
||||||
|
{numeric_junk} {
|
||||||
mmfatal(PARSE_ERROR, "trailing junk after numeric literal");
|
mmfatal(PARSE_ERROR, "trailing junk after numeric literal");
|
||||||
}
|
}
|
||||||
{real_junk} {
|
{real_junk} {
|
||||||
@ -1036,19 +1067,6 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
return S_ANYTHING;
|
return S_ANYTHING;
|
||||||
}
|
}
|
||||||
<C>{ccomment} { ECHO; }
|
<C>{ccomment} { ECHO; }
|
||||||
<C>{xch} {
|
|
||||||
char* endptr;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
base_yylval.ival = strtoul((char *) yytext, &endptr, 16);
|
|
||||||
if (*endptr != '\0' || errno == ERANGE)
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
base_yylval.str = mm_strdup(yytext);
|
|
||||||
return SCONST;
|
|
||||||
}
|
|
||||||
return ICONST;
|
|
||||||
}
|
|
||||||
<C>{cppinclude} {
|
<C>{cppinclude} {
|
||||||
if (system_includes)
|
if (system_includes)
|
||||||
{
|
{
|
||||||
@ -1573,17 +1591,17 @@ addlitchar(unsigned char ychar)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process {integer}. Note this will also do the right thing with {decimal},
|
* Process {decinteger}, {hexinteger}, etc. Note this will also do the right
|
||||||
* ie digits and a decimal point.
|
* thing with {numeric}, ie digits and a decimal point.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
process_integer_literal(const char *token, YYSTYPE *lval)
|
process_integer_literal(const char *token, YYSTYPE *lval, int base)
|
||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
val = strtoint(token, &endptr, 10);
|
val = strtoint(base == 10 ? token : token + 2, &endptr, base);
|
||||||
if (*endptr != '\0' || errno == ERANGE)
|
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 */
|
||||||
|
@ -329,3 +329,95 @@ FROM (VALUES (-2.5::numeric),
|
|||||||
2.5 | 3
|
2.5 | 3
|
||||||
(7 rows)
|
(7 rows)
|
||||||
|
|
||||||
|
-- non-decimal literals
|
||||||
|
SELECT int2 '0b100101';
|
||||||
|
int2
|
||||||
|
------
|
||||||
|
37
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '0o273';
|
||||||
|
int2
|
||||||
|
------
|
||||||
|
187
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '0x42F';
|
||||||
|
int2
|
||||||
|
------
|
||||||
|
1071
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '0b';
|
||||||
|
ERROR: invalid input syntax for type smallint: "0b"
|
||||||
|
LINE 1: SELECT int2 '0b';
|
||||||
|
^
|
||||||
|
SELECT int2 '0o';
|
||||||
|
ERROR: invalid input syntax for type smallint: "0o"
|
||||||
|
LINE 1: SELECT int2 '0o';
|
||||||
|
^
|
||||||
|
SELECT int2 '0x';
|
||||||
|
ERROR: invalid input syntax for type smallint: "0x"
|
||||||
|
LINE 1: SELECT int2 '0x';
|
||||||
|
^
|
||||||
|
-- cases near overflow
|
||||||
|
SELECT int2 '0b111111111111111';
|
||||||
|
int2
|
||||||
|
-------
|
||||||
|
32767
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '0b1000000000000000';
|
||||||
|
ERROR: value "0b1000000000000000" is out of range for type smallint
|
||||||
|
LINE 1: SELECT int2 '0b1000000000000000';
|
||||||
|
^
|
||||||
|
SELECT int2 '0o77777';
|
||||||
|
int2
|
||||||
|
-------
|
||||||
|
32767
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '0o100000';
|
||||||
|
ERROR: value "0o100000" is out of range for type smallint
|
||||||
|
LINE 1: SELECT int2 '0o100000';
|
||||||
|
^
|
||||||
|
SELECT int2 '0x7FFF';
|
||||||
|
int2
|
||||||
|
-------
|
||||||
|
32767
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '0x8000';
|
||||||
|
ERROR: value "0x8000" is out of range for type smallint
|
||||||
|
LINE 1: SELECT int2 '0x8000';
|
||||||
|
^
|
||||||
|
SELECT int2 '-0b1000000000000000';
|
||||||
|
int2
|
||||||
|
--------
|
||||||
|
-32768
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '-0b1000000000000001';
|
||||||
|
ERROR: value "-0b1000000000000001" is out of range for type smallint
|
||||||
|
LINE 1: SELECT int2 '-0b1000000000000001';
|
||||||
|
^
|
||||||
|
SELECT int2 '-0o100000';
|
||||||
|
int2
|
||||||
|
--------
|
||||||
|
-32768
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '-0o100001';
|
||||||
|
ERROR: value "-0o100001" is out of range for type smallint
|
||||||
|
LINE 1: SELECT int2 '-0o100001';
|
||||||
|
^
|
||||||
|
SELECT int2 '-0x8000';
|
||||||
|
int2
|
||||||
|
--------
|
||||||
|
-32768
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int2 '-0x8001';
|
||||||
|
ERROR: value "-0x8001" is out of range for type smallint
|
||||||
|
LINE 1: SELECT int2 '-0x8001';
|
||||||
|
^
|
||||||
|
@ -456,3 +456,95 @@ SELECT lcm((-2147483648)::int4, 1::int4); -- overflow
|
|||||||
ERROR: integer out of range
|
ERROR: integer out of range
|
||||||
SELECT lcm(2147483647::int4, 2147483646::int4); -- overflow
|
SELECT lcm(2147483647::int4, 2147483646::int4); -- overflow
|
||||||
ERROR: integer out of range
|
ERROR: integer out of range
|
||||||
|
-- non-decimal literals
|
||||||
|
SELECT int4 '0b100101';
|
||||||
|
int4
|
||||||
|
------
|
||||||
|
37
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '0o273';
|
||||||
|
int4
|
||||||
|
------
|
||||||
|
187
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '0x42F';
|
||||||
|
int4
|
||||||
|
------
|
||||||
|
1071
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '0b';
|
||||||
|
ERROR: invalid input syntax for type integer: "0b"
|
||||||
|
LINE 1: SELECT int4 '0b';
|
||||||
|
^
|
||||||
|
SELECT int4 '0o';
|
||||||
|
ERROR: invalid input syntax for type integer: "0o"
|
||||||
|
LINE 1: SELECT int4 '0o';
|
||||||
|
^
|
||||||
|
SELECT int4 '0x';
|
||||||
|
ERROR: invalid input syntax for type integer: "0x"
|
||||||
|
LINE 1: SELECT int4 '0x';
|
||||||
|
^
|
||||||
|
-- cases near overflow
|
||||||
|
SELECT int4 '0b1111111111111111111111111111111';
|
||||||
|
int4
|
||||||
|
------------
|
||||||
|
2147483647
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '0b10000000000000000000000000000000';
|
||||||
|
ERROR: value "0b10000000000000000000000000000000" is out of range for type integer
|
||||||
|
LINE 1: SELECT int4 '0b10000000000000000000000000000000';
|
||||||
|
^
|
||||||
|
SELECT int4 '0o17777777777';
|
||||||
|
int4
|
||||||
|
------------
|
||||||
|
2147483647
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '0o20000000000';
|
||||||
|
ERROR: value "0o20000000000" is out of range for type integer
|
||||||
|
LINE 1: SELECT int4 '0o20000000000';
|
||||||
|
^
|
||||||
|
SELECT int4 '0x7FFFFFFF';
|
||||||
|
int4
|
||||||
|
------------
|
||||||
|
2147483647
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '0x80000000';
|
||||||
|
ERROR: value "0x80000000" is out of range for type integer
|
||||||
|
LINE 1: SELECT int4 '0x80000000';
|
||||||
|
^
|
||||||
|
SELECT int4 '-0b10000000000000000000000000000000';
|
||||||
|
int4
|
||||||
|
-------------
|
||||||
|
-2147483648
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '-0b10000000000000000000000000000001';
|
||||||
|
ERROR: value "-0b10000000000000000000000000000001" is out of range for type integer
|
||||||
|
LINE 1: SELECT int4 '-0b10000000000000000000000000000001';
|
||||||
|
^
|
||||||
|
SELECT int4 '-0o20000000000';
|
||||||
|
int4
|
||||||
|
-------------
|
||||||
|
-2147483648
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '-0o20000000001';
|
||||||
|
ERROR: value "-0o20000000001" is out of range for type integer
|
||||||
|
LINE 1: SELECT int4 '-0o20000000001';
|
||||||
|
^
|
||||||
|
SELECT int4 '-0x80000000';
|
||||||
|
int4
|
||||||
|
-------------
|
||||||
|
-2147483648
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int4 '-0x80000001';
|
||||||
|
ERROR: value "-0x80000001" is out of range for type integer
|
||||||
|
LINE 1: SELECT int4 '-0x80000001';
|
||||||
|
^
|
||||||
|
@ -952,3 +952,95 @@ SELECT lcm((-9223372036854775808)::int8, 1::int8); -- overflow
|
|||||||
ERROR: bigint out of range
|
ERROR: bigint out of range
|
||||||
SELECT lcm(9223372036854775807::int8, 9223372036854775806::int8); -- overflow
|
SELECT lcm(9223372036854775807::int8, 9223372036854775806::int8); -- overflow
|
||||||
ERROR: bigint out of range
|
ERROR: bigint out of range
|
||||||
|
-- non-decimal literals
|
||||||
|
SELECT int8 '0b100101';
|
||||||
|
int8
|
||||||
|
------
|
||||||
|
37
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '0o273';
|
||||||
|
int8
|
||||||
|
------
|
||||||
|
187
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '0x42F';
|
||||||
|
int8
|
||||||
|
------
|
||||||
|
1071
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '0b';
|
||||||
|
ERROR: invalid input syntax for type bigint: "0b"
|
||||||
|
LINE 1: SELECT int8 '0b';
|
||||||
|
^
|
||||||
|
SELECT int8 '0o';
|
||||||
|
ERROR: invalid input syntax for type bigint: "0o"
|
||||||
|
LINE 1: SELECT int8 '0o';
|
||||||
|
^
|
||||||
|
SELECT int8 '0x';
|
||||||
|
ERROR: invalid input syntax for type bigint: "0x"
|
||||||
|
LINE 1: SELECT int8 '0x';
|
||||||
|
^
|
||||||
|
-- cases near overflow
|
||||||
|
SELECT int8 '0b111111111111111111111111111111111111111111111111111111111111111';
|
||||||
|
int8
|
||||||
|
---------------------
|
||||||
|
9223372036854775807
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '0b1000000000000000000000000000000000000000000000000000000000000000';
|
||||||
|
ERROR: value "0b1000000000000000000000000000000000000000000000000000000000000000" is out of range for type bigint
|
||||||
|
LINE 1: SELECT int8 '0b100000000000000000000000000000000000000000000...
|
||||||
|
^
|
||||||
|
SELECT int8 '0o777777777777777777777';
|
||||||
|
int8
|
||||||
|
---------------------
|
||||||
|
9223372036854775807
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '0o1000000000000000000000';
|
||||||
|
ERROR: value "0o1000000000000000000000" is out of range for type bigint
|
||||||
|
LINE 1: SELECT int8 '0o1000000000000000000000';
|
||||||
|
^
|
||||||
|
SELECT int8 '0x7FFFFFFFFFFFFFFF';
|
||||||
|
int8
|
||||||
|
---------------------
|
||||||
|
9223372036854775807
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '0x8000000000000000';
|
||||||
|
ERROR: value "0x8000000000000000" is out of range for type bigint
|
||||||
|
LINE 1: SELECT int8 '0x8000000000000000';
|
||||||
|
^
|
||||||
|
SELECT int8 '-0b1000000000000000000000000000000000000000000000000000000000000000';
|
||||||
|
int8
|
||||||
|
----------------------
|
||||||
|
-9223372036854775808
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '-0b1000000000000000000000000000000000000000000000000000000000000001';
|
||||||
|
ERROR: value "-0b1000000000000000000000000000000000000000000000000000000000000001" is out of range for type bigint
|
||||||
|
LINE 1: SELECT int8 '-0b10000000000000000000000000000000000000000000...
|
||||||
|
^
|
||||||
|
SELECT int8 '-0o1000000000000000000000';
|
||||||
|
int8
|
||||||
|
----------------------
|
||||||
|
-9223372036854775808
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '-0o1000000000000000000001';
|
||||||
|
ERROR: value "-0o1000000000000000000001" is out of range for type bigint
|
||||||
|
LINE 1: SELECT int8 '-0o1000000000000000000001';
|
||||||
|
^
|
||||||
|
SELECT int8 '-0x8000000000000000';
|
||||||
|
int8
|
||||||
|
----------------------
|
||||||
|
-9223372036854775808
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT int8 '-0x8000000000000001';
|
||||||
|
ERROR: value "-0x8000000000000001" is out of range for type bigint
|
||||||
|
LINE 1: SELECT int8 '-0x8000000000000001';
|
||||||
|
^
|
||||||
|
@ -3,14 +3,167 @@
|
|||||||
-- Test various combinations of numeric types and functions.
|
-- Test various combinations of numeric types and functions.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- Trailing junk in numeric literals
|
-- numeric literals
|
||||||
--
|
--
|
||||||
|
SELECT 0b100101;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
37
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0o273;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
187
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0x42F;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
1071
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- cases near int4 overflow
|
||||||
|
SELECT 0b1111111111111111111111111111111;
|
||||||
|
?column?
|
||||||
|
------------
|
||||||
|
2147483647
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0b10000000000000000000000000000000;
|
||||||
|
?column?
|
||||||
|
------------
|
||||||
|
2147483648
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0o17777777777;
|
||||||
|
?column?
|
||||||
|
------------
|
||||||
|
2147483647
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0o20000000000;
|
||||||
|
?column?
|
||||||
|
------------
|
||||||
|
2147483648
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0x7FFFFFFF;
|
||||||
|
?column?
|
||||||
|
------------
|
||||||
|
2147483647
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0x80000000;
|
||||||
|
?column?
|
||||||
|
------------
|
||||||
|
2147483648
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT -0b10000000000000000000000000000000;
|
||||||
|
?column?
|
||||||
|
-------------
|
||||||
|
-2147483648
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT -0b10000000000000000000000000000001;
|
||||||
|
?column?
|
||||||
|
-------------
|
||||||
|
-2147483649
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT -0o20000000000;
|
||||||
|
?column?
|
||||||
|
-------------
|
||||||
|
-2147483648
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT -0o20000000001;
|
||||||
|
?column?
|
||||||
|
-------------
|
||||||
|
-2147483649
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT -0x80000000;
|
||||||
|
?column?
|
||||||
|
-------------
|
||||||
|
-2147483648
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT -0x80000001;
|
||||||
|
?column?
|
||||||
|
-------------
|
||||||
|
-2147483649
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- cases near int8 overflow
|
||||||
|
SELECT 0b111111111111111111111111111111111111111111111111111111111111111;
|
||||||
|
?column?
|
||||||
|
---------------------
|
||||||
|
9223372036854775807
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0b1000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
ERROR: invalid input syntax for type numeric: "0b1000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
LINE 1: SELECT 0b100000000000000000000000000000000000000000000000000...
|
||||||
|
^
|
||||||
|
SELECT 0o777777777777777777777;
|
||||||
|
?column?
|
||||||
|
---------------------
|
||||||
|
9223372036854775807
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0o1000000000000000000000;
|
||||||
|
ERROR: invalid input syntax for type numeric: "0o1000000000000000000000"
|
||||||
|
LINE 1: SELECT 0o1000000000000000000000;
|
||||||
|
^
|
||||||
|
SELECT 0x7FFFFFFFFFFFFFFF;
|
||||||
|
?column?
|
||||||
|
---------------------
|
||||||
|
9223372036854775807
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 0x8000000000000000;
|
||||||
|
ERROR: invalid input syntax for type numeric: "0x8000000000000000"
|
||||||
|
LINE 1: SELECT 0x8000000000000000;
|
||||||
|
^
|
||||||
|
SELECT -0b1000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
?column?
|
||||||
|
----------------------
|
||||||
|
-9223372036854775808
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT -0b1000000000000000000000000000000000000000000000000000000000000001;
|
||||||
|
ERROR: invalid input syntax for type numeric: "-0b1000000000000000000000000000000000000000000000000000000000000001"
|
||||||
|
LINE 1: SELECT -0b10000000000000000000000000000000000000000000000000...
|
||||||
|
^
|
||||||
|
SELECT -0o1000000000000000000000;
|
||||||
|
?column?
|
||||||
|
----------------------
|
||||||
|
-9223372036854775808
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT -0o1000000000000000000001;
|
||||||
|
ERROR: invalid input syntax for type numeric: "-0o1000000000000000000001"
|
||||||
|
LINE 1: SELECT -0o1000000000000000000001;
|
||||||
|
^
|
||||||
|
SELECT -0x8000000000000000;
|
||||||
|
?column?
|
||||||
|
----------------------
|
||||||
|
-9223372036854775808
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT -0x8000000000000001;
|
||||||
|
ERROR: invalid input syntax for type numeric: "-0x8000000000000001"
|
||||||
|
LINE 1: SELECT -0x8000000000000001;
|
||||||
|
^
|
||||||
|
-- error cases
|
||||||
SELECT 123abc;
|
SELECT 123abc;
|
||||||
ERROR: trailing junk after numeric literal at or near "123a"
|
ERROR: trailing junk after numeric literal at or near "123a"
|
||||||
LINE 1: SELECT 123abc;
|
LINE 1: SELECT 123abc;
|
||||||
^
|
^
|
||||||
SELECT 0x0o;
|
SELECT 0x0o;
|
||||||
ERROR: trailing junk after numeric literal at or near "0x"
|
ERROR: trailing junk after numeric literal at or near "0x0o"
|
||||||
LINE 1: SELECT 0x0o;
|
LINE 1: SELECT 0x0o;
|
||||||
^
|
^
|
||||||
SELECT 1_2_3;
|
SELECT 1_2_3;
|
||||||
@ -45,6 +198,42 @@ PREPARE p1 AS SELECT $1a;
|
|||||||
ERROR: trailing junk after parameter at or near "$1a"
|
ERROR: trailing junk after parameter at or near "$1a"
|
||||||
LINE 1: PREPARE p1 AS SELECT $1a;
|
LINE 1: PREPARE p1 AS SELECT $1a;
|
||||||
^
|
^
|
||||||
|
SELECT 0b;
|
||||||
|
ERROR: invalid binary integer at or near "0b"
|
||||||
|
LINE 1: SELECT 0b;
|
||||||
|
^
|
||||||
|
SELECT 1b;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "1b"
|
||||||
|
LINE 1: SELECT 1b;
|
||||||
|
^
|
||||||
|
SELECT 0b0x;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "0b0x"
|
||||||
|
LINE 1: SELECT 0b0x;
|
||||||
|
^
|
||||||
|
SELECT 0o;
|
||||||
|
ERROR: invalid octal integer at or near "0o"
|
||||||
|
LINE 1: SELECT 0o;
|
||||||
|
^
|
||||||
|
SELECT 1o;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "1o"
|
||||||
|
LINE 1: SELECT 1o;
|
||||||
|
^
|
||||||
|
SELECT 0o0x;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "0o0x"
|
||||||
|
LINE 1: SELECT 0o0x;
|
||||||
|
^
|
||||||
|
SELECT 0x;
|
||||||
|
ERROR: invalid hexadecimal integer at or near "0x"
|
||||||
|
LINE 1: SELECT 0x;
|
||||||
|
^
|
||||||
|
SELECT 1x;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "1x"
|
||||||
|
LINE 1: SELECT 1x;
|
||||||
|
^
|
||||||
|
SELECT 0x0y;
|
||||||
|
ERROR: trailing junk after numeric literal at or near "0x0y"
|
||||||
|
LINE 1: SELECT 0x0y;
|
||||||
|
^
|
||||||
--
|
--
|
||||||
-- Test implicit type conversions
|
-- Test implicit type conversions
|
||||||
-- This fails for Postgres v6.1 (and earlier?)
|
-- This fails for Postgres v6.1 (and earlier?)
|
||||||
|
@ -110,3 +110,29 @@ FROM (VALUES (-2.5::numeric),
|
|||||||
(0.5::numeric),
|
(0.5::numeric),
|
||||||
(1.5::numeric),
|
(1.5::numeric),
|
||||||
(2.5::numeric)) t(x);
|
(2.5::numeric)) t(x);
|
||||||
|
|
||||||
|
|
||||||
|
-- non-decimal literals
|
||||||
|
|
||||||
|
SELECT int2 '0b100101';
|
||||||
|
SELECT int2 '0o273';
|
||||||
|
SELECT int2 '0x42F';
|
||||||
|
|
||||||
|
SELECT int2 '0b';
|
||||||
|
SELECT int2 '0o';
|
||||||
|
SELECT int2 '0x';
|
||||||
|
|
||||||
|
-- cases near overflow
|
||||||
|
SELECT int2 '0b111111111111111';
|
||||||
|
SELECT int2 '0b1000000000000000';
|
||||||
|
SELECT int2 '0o77777';
|
||||||
|
SELECT int2 '0o100000';
|
||||||
|
SELECT int2 '0x7FFF';
|
||||||
|
SELECT int2 '0x8000';
|
||||||
|
|
||||||
|
SELECT int2 '-0b1000000000000000';
|
||||||
|
SELECT int2 '-0b1000000000000001';
|
||||||
|
SELECT int2 '-0o100000';
|
||||||
|
SELECT int2 '-0o100001';
|
||||||
|
SELECT int2 '-0x8000';
|
||||||
|
SELECT int2 '-0x8001';
|
||||||
|
@ -170,3 +170,29 @@ FROM (VALUES (0::int4, 0::int4),
|
|||||||
|
|
||||||
SELECT lcm((-2147483648)::int4, 1::int4); -- overflow
|
SELECT lcm((-2147483648)::int4, 1::int4); -- overflow
|
||||||
SELECT lcm(2147483647::int4, 2147483646::int4); -- overflow
|
SELECT lcm(2147483647::int4, 2147483646::int4); -- overflow
|
||||||
|
|
||||||
|
|
||||||
|
-- non-decimal literals
|
||||||
|
|
||||||
|
SELECT int4 '0b100101';
|
||||||
|
SELECT int4 '0o273';
|
||||||
|
SELECT int4 '0x42F';
|
||||||
|
|
||||||
|
SELECT int4 '0b';
|
||||||
|
SELECT int4 '0o';
|
||||||
|
SELECT int4 '0x';
|
||||||
|
|
||||||
|
-- cases near overflow
|
||||||
|
SELECT int4 '0b1111111111111111111111111111111';
|
||||||
|
SELECT int4 '0b10000000000000000000000000000000';
|
||||||
|
SELECT int4 '0o17777777777';
|
||||||
|
SELECT int4 '0o20000000000';
|
||||||
|
SELECT int4 '0x7FFFFFFF';
|
||||||
|
SELECT int4 '0x80000000';
|
||||||
|
|
||||||
|
SELECT int4 '-0b10000000000000000000000000000000';
|
||||||
|
SELECT int4 '-0b10000000000000000000000000000001';
|
||||||
|
SELECT int4 '-0o20000000000';
|
||||||
|
SELECT int4 '-0o20000000001';
|
||||||
|
SELECT int4 '-0x80000000';
|
||||||
|
SELECT int4 '-0x80000001';
|
||||||
|
@ -251,3 +251,29 @@ FROM (VALUES (0::int8, 0::int8),
|
|||||||
|
|
||||||
SELECT lcm((-9223372036854775808)::int8, 1::int8); -- overflow
|
SELECT lcm((-9223372036854775808)::int8, 1::int8); -- overflow
|
||||||
SELECT lcm(9223372036854775807::int8, 9223372036854775806::int8); -- overflow
|
SELECT lcm(9223372036854775807::int8, 9223372036854775806::int8); -- overflow
|
||||||
|
|
||||||
|
|
||||||
|
-- non-decimal literals
|
||||||
|
|
||||||
|
SELECT int8 '0b100101';
|
||||||
|
SELECT int8 '0o273';
|
||||||
|
SELECT int8 '0x42F';
|
||||||
|
|
||||||
|
SELECT int8 '0b';
|
||||||
|
SELECT int8 '0o';
|
||||||
|
SELECT int8 '0x';
|
||||||
|
|
||||||
|
-- cases near overflow
|
||||||
|
SELECT int8 '0b111111111111111111111111111111111111111111111111111111111111111';
|
||||||
|
SELECT int8 '0b1000000000000000000000000000000000000000000000000000000000000000';
|
||||||
|
SELECT int8 '0o777777777777777777777';
|
||||||
|
SELECT int8 '0o1000000000000000000000';
|
||||||
|
SELECT int8 '0x7FFFFFFFFFFFFFFF';
|
||||||
|
SELECT int8 '0x8000000000000000';
|
||||||
|
|
||||||
|
SELECT int8 '-0b1000000000000000000000000000000000000000000000000000000000000000';
|
||||||
|
SELECT int8 '-0b1000000000000000000000000000000000000000000000000000000000000001';
|
||||||
|
SELECT int8 '-0o1000000000000000000000';
|
||||||
|
SELECT int8 '-0o1000000000000000000001';
|
||||||
|
SELECT int8 '-0x8000000000000000';
|
||||||
|
SELECT int8 '-0x8000000000000001';
|
||||||
|
@ -3,10 +3,46 @@
|
|||||||
-- Test various combinations of numeric types and functions.
|
-- Test various combinations of numeric types and functions.
|
||||||
--
|
--
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Trailing junk in numeric literals
|
-- numeric literals
|
||||||
--
|
--
|
||||||
|
|
||||||
|
SELECT 0b100101;
|
||||||
|
SELECT 0o273;
|
||||||
|
SELECT 0x42F;
|
||||||
|
|
||||||
|
-- cases near int4 overflow
|
||||||
|
SELECT 0b1111111111111111111111111111111;
|
||||||
|
SELECT 0b10000000000000000000000000000000;
|
||||||
|
SELECT 0o17777777777;
|
||||||
|
SELECT 0o20000000000;
|
||||||
|
SELECT 0x7FFFFFFF;
|
||||||
|
SELECT 0x80000000;
|
||||||
|
|
||||||
|
SELECT -0b10000000000000000000000000000000;
|
||||||
|
SELECT -0b10000000000000000000000000000001;
|
||||||
|
SELECT -0o20000000000;
|
||||||
|
SELECT -0o20000000001;
|
||||||
|
SELECT -0x80000000;
|
||||||
|
SELECT -0x80000001;
|
||||||
|
|
||||||
|
-- cases near int8 overflow
|
||||||
|
SELECT 0b111111111111111111111111111111111111111111111111111111111111111;
|
||||||
|
SELECT 0b1000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
SELECT 0o777777777777777777777;
|
||||||
|
SELECT 0o1000000000000000000000;
|
||||||
|
SELECT 0x7FFFFFFFFFFFFFFF;
|
||||||
|
SELECT 0x8000000000000000;
|
||||||
|
|
||||||
|
SELECT -0b1000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
SELECT -0b1000000000000000000000000000000000000000000000000000000000000001;
|
||||||
|
SELECT -0o1000000000000000000000;
|
||||||
|
SELECT -0o1000000000000000000001;
|
||||||
|
SELECT -0x8000000000000000;
|
||||||
|
SELECT -0x8000000000000001;
|
||||||
|
|
||||||
|
-- error cases
|
||||||
SELECT 123abc;
|
SELECT 123abc;
|
||||||
SELECT 0x0o;
|
SELECT 0x0o;
|
||||||
SELECT 1_2_3;
|
SELECT 1_2_3;
|
||||||
@ -18,6 +54,19 @@ SELECT 0.0e;
|
|||||||
SELECT 0.0e+a;
|
SELECT 0.0e+a;
|
||||||
PREPARE p1 AS SELECT $1a;
|
PREPARE p1 AS SELECT $1a;
|
||||||
|
|
||||||
|
SELECT 0b;
|
||||||
|
SELECT 1b;
|
||||||
|
SELECT 0b0x;
|
||||||
|
|
||||||
|
SELECT 0o;
|
||||||
|
SELECT 1o;
|
||||||
|
SELECT 0o0x;
|
||||||
|
|
||||||
|
SELECT 0x;
|
||||||
|
SELECT 1x;
|
||||||
|
SELECT 0x0y;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Test implicit type conversions
|
-- Test implicit type conversions
|
||||||
-- This fails for Postgres v6.1 (and earlier?)
|
-- This fails for Postgres v6.1 (and earlier?)
|
||||||
|
Reference in New Issue
Block a user