Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

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

Provide feedback

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

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6fcda9a

Browse files
committed
Non-decimal integer literals
Add support for hexadecimal, octal, and binary integer literals: 0x42F 0o273 0b100101per SQL:202x draft.This adds support in the lexer as well as in the integer type inputfunctions.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
1 parent60684dd commit6fcda9a

File tree

16 files changed

+1028
-118
lines changed

16 files changed

+1028
-118
lines changed

‎doc/src/sgml/syntax.sgml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,40 @@ $function$
694694
</literallayout>
695695
</para>
696696

697+
<para>
698+
Additionally, non-decimal integer constants can be used in these forms:
699+
<synopsis>
700+
0x<replaceable>hexdigits</replaceable>
701+
0o<replaceable>octdigits</replaceable>
702+
0b<replaceable>bindigits</replaceable>
703+
</synopsis>
704+
<replaceable>hexdigits</replaceable> is one or more hexadecimal digits
705+
(0-9, A-F), <replaceable>octdigits</replaceable> is one or more octal
706+
digits (0-7), <replaceable>bindigits</replaceable> is one or more binary
707+
digits (0 or 1). Hexadecimal digits and the radix prefixes can be in
708+
upper or lower case. Note that only integers can have non-decimal forms,
709+
not numbers with fractional parts.
710+
</para>
711+
712+
<para>
713+
These are some examples of this:
714+
<literallayout>0b100101
715+
0B10011001
716+
0o273
717+
0O755
718+
0x42f
719+
0XFFFF
720+
</literallayout>
721+
</para>
722+
723+
<note>
724+
<para>
725+
Nondecimal integer constants are currently only supported in the range
726+
of the <type>bigint</type> type (see <xref
727+
linkend="datatype-numeric-table"/>).
728+
</para>
729+
</note>
730+
697731
<para>
698732
<indexterm><primary>integer</primary></indexterm>
699733
<indexterm><primary>bigint</primary></indexterm>

‎src/backend/catalog/information_schema.sql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ RETURN
119119
WHEN1700/*numeric*/ THEN
120120
CASE WHEN $2=-1
121121
THENnull
122-
ELSE (($2-4)>>16) &65535
122+
ELSE (($2-4)>>16) &0xFFFF
123123
END
124124
WHEN700/*float4*/ THEN24/*FLT_MANT_DIG*/
125125
WHEN701/*float8*/ THEN53/*DBL_MANT_DIG*/
@@ -147,7 +147,7 @@ RETURN
147147
WHEN $1IN (1700) THEN
148148
CASE WHEN $2=-1
149149
THENnull
150-
ELSE ($2-4) &65535
150+
ELSE ($2-4) &0xFFFF
151151
END
152152
ELSEnull
153153
END;
@@ -163,7 +163,7 @@ RETURN
163163
WHEN $1IN (1083,1114,1184,1266)/* time, timestamp, same + tz*/
164164
THEN CASE WHEN $2<0 THEN6 ELSE $2 END
165165
WHEN $1IN (1186)/* interval*/
166-
THEN CASE WHEN $2<0OR $2 &65535=65535 THEN6 ELSE $2 &65535 END
166+
THEN CASE WHEN $2<0OR $2 &0xFFFF=0xFFFF THEN6 ELSE $2 &0xFFFF END
167167
ELSEnull
168168
END;
169169

‎src/backend/catalog/sql_features.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ T652SQL-dynamic statements in SQL routinesNO
527527
T653SQL-schema statements in external routinesYES
528528
T654SQL-dynamic statements in external routinesNO
529529
T655Cyclically dependent routinesYES
530+
T661Non-decimal integer literalsYESSQL:202x draft
530531
T811Basic SQL/JSON constructor functionsNO
531532
T812SQL/JSON: JSON_OBJECTAGGNO
532533
T813SQL/JSON: JSON_ARRAYAGG with ORDER BYNO

‎src/backend/parser/parse_node.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,46 @@ make_const(ParseState *pstate, A_Const *aconst)
385385
{
386386
/* could be an oversize integer as well as a float ... */
387387

388+
intbase=10;
389+
char*startptr;
390+
intsign;
391+
char*testvalue;
388392
int64val64;
389393
char*endptr;
390394

395+
startptr=aconst->val.fval.fval;
396+
if (startptr[0]=='-')
397+
{
398+
sign=-1;
399+
startptr++;
400+
}
401+
else
402+
sign=+1;
403+
if (startptr[0]=='0')
404+
{
405+
if (startptr[1]=='b'||startptr[1]=='B')
406+
{
407+
base=2;
408+
startptr+=2;
409+
}
410+
elseif (startptr[1]=='o'||startptr[1]=='O')
411+
{
412+
base=8;
413+
startptr+=2;
414+
}
415+
if (startptr[1]=='x'||startptr[1]=='X')
416+
{
417+
base=16;
418+
startptr+=2;
419+
}
420+
}
421+
422+
if (sign==+1)
423+
testvalue=startptr;
424+
else
425+
testvalue=psprintf("-%s",startptr);
391426
errno=0;
392-
val64=strtoi64(aconst->val.fval.fval,&endptr,10);
427+
val64=strtoi64(testvalue,&endptr,base);
393428
if (errno==0&&*endptr=='\0')
394429
{
395430
/*

‎src/backend/parser/scan.l

Lines changed: 76 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ static void addlit(char *ytext, int yleng, core_yyscan_t yyscanner);
124124
staticvoidaddlitchar(unsignedchar ychar,core_yyscan_t yyscanner);
125125
staticchar *litbufdup(core_yyscan_t yyscanner);
126126
staticunsignedcharunescape_single_char(unsignedchar c,core_yyscan_t yyscanner);
127-
staticintprocess_integer_literal(constchar *token, YYSTYPE *lval);
127+
staticintprocess_integer_literal(constchar *token, YYSTYPE *lval,int base);
128128
staticvoidaddunicode(pg_wchar c,yyscan_t yyscanner);
129129

130130
#defineyyerror(msg) scanner_yyerror(msg, yyscanner)
@@ -385,25 +385,40 @@ operator{op_chars}+
385385
* Unary minus is not part of a number here. Instead we pass it separately to
386386
* the parser, and there it gets coerced via doNegate().
387387
*
388-
* {decimalfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
388+
* {numericfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
389389
*
390390
* {realfail} is added to prevent the need for scanner
391391
* backup when the {real} rule fails to match completely.
392392
*/
393-
digit[0-9]
394-
395-
integer{digit}+
396-
decimal(({digit}*\.{digit}+)|({digit}+\.{digit}*))
397-
decimalfail{digit}+\.\.
398-
real({integer}|{decimal})[Ee][-+]?{digit}+
399-
realfail({integer}|{decimal})[Ee][-+]
400-
401-
integer_junk{integer}{ident_start}
402-
decimal_junk{decimal}{ident_start}
393+
decdigit[0-9]
394+
hexdigit[0-9A-Fa-f]
395+
octdigit[0-7]
396+
bindigit[0-1]
397+
398+
decinteger{decdigit}+
399+
hexinteger0[xX]{hexdigit}+
400+
octinteger0[oO]{octdigit}+
401+
bininteger0[bB]{bindigit}+
402+
403+
hexfail0[xX]
404+
octfail0[oO]
405+
binfail0[bB]
406+
407+
numeric(({decinteger}\.{decinteger}?)|(\.{decinteger}))
408+
numericfail{decdigit}+\.\.
409+
410+
real({decinteger}|{numeric})[Ee][-+]?{decdigit}+
411+
realfail({decinteger}|{numeric})[Ee][-+]
412+
413+
decinteger_junk{decinteger}{ident_start}
414+
hexinteger_junk{hexinteger}{ident_start}
415+
octinteger_junk{octinteger}{ident_start}
416+
bininteger_junk{bininteger}{ident_start}
417+
numeric_junk{numeric}{ident_start}
403418
real_junk{real}{ident_start}
404419

405-
param\${integer}
406-
param_junk\${integer}{ident_start}
420+
param\${decinteger}
421+
param_junk\${decinteger}{ident_start}
407422

408423
other.
409424

@@ -983,20 +998,44 @@ other.
983998
yyerror("trailing junk after parameter");
984999
}
9851000

986-
{integer}{
1001+
{decinteger}{
1002+
SET_YYLLOC();
1003+
returnprocess_integer_literal(yytext, yylval,10);
1004+
}
1005+
{hexinteger}{
1006+
SET_YYLLOC();
1007+
returnprocess_integer_literal(yytext, yylval,16);
1008+
}
1009+
{octinteger}{
1010+
SET_YYLLOC();
1011+
returnprocess_integer_literal(yytext, yylval,8);
1012+
}
1013+
{bininteger}{
1014+
SET_YYLLOC();
1015+
returnprocess_integer_literal(yytext, yylval,2);
1016+
}
1017+
{hexfail}{
1018+
SET_YYLLOC();
1019+
yyerror("invalid hexadecimal integer");
1020+
}
1021+
{octfail}{
9871022
SET_YYLLOC();
988-
returnprocess_integer_literal(yytext, yylval);
1023+
yyerror("invalid octal integer");
9891024
}
990-
{decimal}{
1025+
{binfail}{
1026+
SET_YYLLOC();
1027+
yyerror("invalid binary integer");
1028+
}
1029+
{numeric}{
9911030
SET_YYLLOC();
9921031
yylval->str =pstrdup(yytext);
9931032
return FCONST;
9941033
}
995-
{decimalfail}{
1034+
{numericfail}{
9961035
/* throw back the .., and treat as integer */
9971036
yyless(yyleng -2);
9981037
SET_YYLLOC();
999-
returnprocess_integer_literal(yytext, yylval);
1038+
returnprocess_integer_literal(yytext, yylval,10);
10001039
}
10011040
{real}{
10021041
SET_YYLLOC();
@@ -1007,11 +1046,23 @@ other.
10071046
SET_YYLLOC();
10081047
yyerror("trailing junk after numeric literal");
10091048
}
1010-
{integer_junk}{
1049+
{decinteger_junk}{
1050+
SET_YYLLOC();
1051+
yyerror("trailing junk after numeric literal");
1052+
}
1053+
{hexinteger_junk}{
1054+
SET_YYLLOC();
1055+
yyerror("trailing junk after numeric literal");
1056+
}
1057+
{octinteger_junk}{
1058+
SET_YYLLOC();
1059+
yyerror("trailing junk after numeric literal");
1060+
}
1061+
{bininteger_junk}{
10111062
SET_YYLLOC();
10121063
yyerror("trailing junk after numeric literal");
10131064
}
1014-
{decimal_junk}{
1065+
{numeric_junk}{
10151066
SET_YYLLOC();
10161067
yyerror("trailing junk after numeric literal");
10171068
}
@@ -1307,17 +1358,17 @@ litbufdup(core_yyscan_t yyscanner)
13071358
}
13081359

13091360
/*
1310-
* Process {integer}. Note this will also do the right thing with {decimal},
1311-
* ie digits and a decimal point.
1361+
* Process {decinteger}, {hexinteger}, etc. Note this will also do the right
1362+
*thing with {numeric},ie digits and a decimal point.
13121363
*/
13131364
staticint
1314-
process_integer_literal(constchar *token, YYSTYPE *lval)
1365+
process_integer_literal(constchar *token, YYSTYPE *lval,int base)
13151366
{
13161367
intval;
13171368
char *endptr;
13181369

13191370
errno =0;
1320-
val =strtoint(token, &endptr,10);
1371+
val =strtoint(base ==10 ?token : token +2, &endptr,base);
13211372
if (*endptr !='\0' || errno == ERANGE)
13221373
{
13231374
/* integer too large (or contains decimal pt), treat it as a float */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp