Skip to content

Commit 2833c73

Browse files
authored
Type specifier suffix for long and int literals (#3434)
This adds two new type specifiers: `i` (or `I`) for `int` and `l` or (`L`) for `long`/`bigint`, consistent with the existing `float` and `double` specifiers. The primary advantage is enhanced precision when specifying literal types for functions, predicates, and especially SQL testing. This improved precision allows for more accurate testing with literals, closely mirroring the behavior of prepared parameters. This fixes #3433 .
1 parent 29cfcd0 commit 2833c73

File tree

6 files changed

+276
-16
lines changed

6 files changed

+276
-16
lines changed

fdb-relational-core/src/main/antlr/RelationalLexer.g4

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,14 +1272,14 @@ FILESIZE_LITERAL: DEC_DIGIT+ ('K'|'M'|'G'|'T');
12721272

12731273
START_NATIONAL_STRING_LITERAL: 'N' SQUOTA_STRING;
12741274
STRING_LITERAL: SQUOTA_STRING;
1275-
DECIMAL_LITERAL: DEC_DIGIT+;
1275+
DECIMAL_LITERAL: DEC_DIGIT+ DECIMAL_TYPE_MODIFIER?;
12761276
HEXADECIMAL_LITERAL: 'X' STRING_LITERAL;
12771277
BASE64_LITERAL: 'B64' STRING_LITERAL;
12781278

1279-
REAL_LITERAL: (DEC_DIGIT+)? '.' DEC_DIGIT+ TYPE_MODIFIER?
1280-
| DEC_DIGIT+ '.' EXPONENT_NUM_PART TYPE_MODIFIER?
1281-
| (DEC_DIGIT+)? '.' (DEC_DIGIT+ EXPONENT_NUM_PART) TYPE_MODIFIER?
1282-
| DEC_DIGIT+ EXPONENT_NUM_PART TYPE_MODIFIER?;
1279+
REAL_LITERAL: (DEC_DIGIT+)? '.' DEC_DIGIT+ REAL_TYPE_MODIFIER?
1280+
| DEC_DIGIT+ '.' EXPONENT_NUM_PART REAL_TYPE_MODIFIER?
1281+
| (DEC_DIGIT+)? '.' (DEC_DIGIT+ EXPONENT_NUM_PART) REAL_TYPE_MODIFIER?
1282+
| DEC_DIGIT+ EXPONENT_NUM_PART REAL_TYPE_MODIFIER?;
12831283
NULL_SPEC_LITERAL: '\\' 'N';
12841284
BIT_STRING: BIT_STRING_L;
12851285
STRING_CHARSET_NAME: '_' CHARSET_NAME;
@@ -1341,7 +1341,10 @@ fragment BIT_STRING_L: 'B' '\'' [01]+ '\'';
13411341

13421342
fragment FLOAT_TYPE_MODIFIER: ('F'|'f');
13431343
fragment DOUBLE_TYPE_MODIFIER: ('D'|'d');
1344-
fragment TYPE_MODIFIER: (FLOAT_TYPE_MODIFIER | DOUBLE_TYPE_MODIFIER);
1344+
fragment REAL_TYPE_MODIFIER: (FLOAT_TYPE_MODIFIER | DOUBLE_TYPE_MODIFIER);
1345+
fragment INT_TYPE_MODIFIER: ('I' | 'i');
1346+
fragment LONG_TYPE_MODIFIER: ('L' | 'l');
1347+
fragment DECIMAL_TYPE_MODIFIER: (INT_TYPE_MODIFIER | LONG_TYPE_MODIFIER);
13451348

13461349

13471350

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ParseHelpers.java

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.apple.foundationdb.relational.generated.RelationalParser;
3131
import com.apple.foundationdb.relational.recordlayer.util.Hex;
3232

33+
import com.apple.foundationdb.relational.util.Assert;
3334
import com.google.common.base.Suppliers;
3435
import com.google.common.collect.ImmutableList;
3536
import org.antlr.v4.runtime.CommonTokenStream;
@@ -63,24 +64,36 @@ private ParseHelpers() {
6364
*/
6465
@Nonnull
6566
public static Object parseDecimal(@Nonnull String valueAsString) {
67+
final var lastCharIdx = valueAsString.length() - 1;
68+
Assert.thatUnchecked(lastCharIdx >= 0);
6669
if (valueAsString.contains(".")) {
67-
final var lastCharacter = valueAsString.charAt(valueAsString.length() - 1);
70+
final var lastCharacter = valueAsString.charAt(lastCharIdx);
6871
switch (lastCharacter) {
69-
case 'f':
72+
case 'f': // fallthrough
7073
case 'F':
71-
return Float.parseFloat(valueAsString.substring(0, valueAsString.length() - 1));
72-
case 'd':
74+
return Float.parseFloat(valueAsString.substring(0, lastCharIdx));
75+
case 'd': // fallthrough
7376
case 'D':
74-
return Double.parseDouble(valueAsString.substring(0, valueAsString.length() - 1));
77+
return Double.parseDouble(valueAsString.substring(0, lastCharIdx));
7578
default:
7679
return Double.parseDouble(valueAsString);
7780
}
7881
} else {
79-
long result = Long.parseLong(valueAsString);
80-
if (Integer.MIN_VALUE <= result && result <= Integer.MAX_VALUE) {
81-
return Math.toIntExact(result);
82-
} else {
83-
return result;
82+
final var lastCharacter = valueAsString.charAt(lastCharIdx);
83+
switch (lastCharacter) {
84+
case 'l': // fallthrough
85+
case 'L':
86+
return Long.parseLong(valueAsString.substring(0, lastCharIdx));
87+
case 'i': // fallthrough
88+
case 'I':
89+
return Integer.parseInt(valueAsString.substring(0, lastCharIdx));
90+
default:
91+
long result = Long.parseLong(valueAsString);
92+
if (Integer.MIN_VALUE <= result && result <= Integer.MAX_VALUE) {
93+
return Math.toIntExact(result);
94+
} else {
95+
return result;
96+
}
8497
}
8598
}
8699
}

yaml-tests/src/test/java/YamlIntegrationTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,10 @@ public void betweenTest(YamlTest.Runner runner) throws Exception {
273273
public void sqlFunctionsTest(YamlTest.Runner runner) throws Exception {
274274
runner.runYamsql("sql-functions.yamsql");
275275
}
276+
277+
@TestTemplate
278+
@MaintainYamlTestConfig(YamlTestConfigFilters.CORRECT_EXPLAIN_AND_METRICS)
279+
public void literalTests(YamlTest.Runner runner) throws Exception {
280+
runner.runYamsql("literal-tests.yamsql");
281+
}
276282
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
2+
@
3+
unnamed-33EXPLAIN select * from B where 6L = coalesce(5L, 6L)�
4+
5+
�ô�#& ���(0���8@6SCAN(<,>) | FILTER @c6 EQUALS coalesce_long(@c10, @c6)�
6+
digraph G {
7+
fontname=courier;
8+
rankdir=BT;
9+
splines=polyline;
10+
1 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE @c6 EQUALS coalesce_long(@c10, @c6)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
11+
2 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Scan</td></tr><tr><td align="left">range: &lt;-∞, ∞&gt;</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
12+
3 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Primary Storage</td></tr><tr><td align="left">record types: [B]</td></tr></table>> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
13+
3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
14+
2 -> 1 [ label=<&nbsp;q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
15+
}�
16+
@
17+
unnamed-33EXPLAIN select * from B where 6L = coalesce(5I, 6I)�
18+
����#& ���(0���8@GSCAN(<,>) | FILTER @c6 EQUALS promote(coalesce_int(@c10, @c12) AS LONG)�
19+
digraph G {
20+
fontname=courier;
21+
rankdir=BT;
22+
splines=polyline;
23+
1 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE @c6 EQUALS promote(coalesce_int(@c10, @c12) AS LONG)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
24+
2 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Scan</td></tr><tr><td align="left">range: &lt;-∞, ∞&gt;</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
25+
3 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Primary Storage</td></tr><tr><td align="left">record types: [B]</td></tr></table>> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
26+
3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
27+
2 -> 1 [ label=<&nbsp;q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
28+
}�
29+
>
30+
unnamed-31EXPLAIN select * from B where 6L = coalesce(5, 6)�
31+
����#& �Ѭ(0��8@GSCAN(<,>) | FILTER @c6 EQUALS promote(coalesce_int(@c10, @c12) AS LONG)�
32+
digraph G {
33+
fontname=courier;
34+
rankdir=BT;
35+
splines=polyline;
36+
1 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE @c6 EQUALS promote(coalesce_int(@c10, @c12) AS LONG)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
37+
2 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Scan</td></tr><tr><td align="left">range: &lt;-∞, ∞&gt;</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
38+
3 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Primary Storage</td></tr><tr><td align="left">record types: [B]</td></tr></table>> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
39+
3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
40+
2 -> 1 [ label=<&nbsp;q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
41+
}�
42+
>
43+
unnamed-31EXPLAIN select * from B where 6 = coalesce(5L, 6)�
44+
����#& ڑ�(0���8@XSCAN(<,>) | FILTER promote(@c6 AS LONG) EQUALS coalesce_long(@c10, promote(@c6 AS LONG))�
45+
digraph G {
46+
fontname=courier;
47+
rankdir=BT;
48+
splines=polyline;
49+
1 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE promote(@c6 AS LONG) EQUALS coalesce_long(@c10, promote(@c6 AS LONG))</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
50+
2 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Scan</td></tr><tr><td align="left">range: &lt;-∞, ∞&gt;</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
51+
3 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Primary Storage</td></tr><tr><td align="left">record types: [B]</td></tr></table>> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
52+
3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
53+
2 -> 1 [ label=<&nbsp;q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
54+
}�
55+
@
56+
unnamed-33EXPLAIN select * from B where 6I = coalesce(5L, 6I)�
57+
����#& ���(0���8@XSCAN(<,>) | FILTER promote(@c6 AS LONG) EQUALS coalesce_long(@c10, promote(@c6 AS LONG))�
58+
digraph G {
59+
fontname=courier;
60+
rankdir=BT;
61+
splines=polyline;
62+
1 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE promote(@c6 AS LONG) EQUALS coalesce_long(@c10, promote(@c6 AS LONG))</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
63+
2 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Scan</td></tr><tr><td align="left">range: &lt;-∞, ∞&gt;</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
64+
3 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Primary Storage</td></tr><tr><td align="left">record types: [B]</td></tr></table>> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
65+
3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
66+
2 -> 1 [ label=<&nbsp;q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
67+
}�
68+
@
69+
unnamed-33EXPLAIN select * from B where 6i = coalesce(5l, 6i)�
70+
���#& ���(0���8@XSCAN(<,>) | FILTER promote(@c6 AS LONG) EQUALS coalesce_long(@c10, promote(@c6 AS LONG))�
71+
digraph G {
72+
fontname=courier;
73+
rankdir=BT;
74+
splines=polyline;
75+
1 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE promote(@c6 AS LONG) EQUALS coalesce_long(@c10, promote(@c6 AS LONG))</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
76+
2 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Scan</td></tr><tr><td align="left">range: &lt;-∞, ∞&gt;</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
77+
3 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Primary Storage</td></tr><tr><td align="left">record types: [B]</td></tr></table>> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
78+
3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
79+
2 -> 1 [ label=<&nbsp;q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
80+
}�
81+
=
82+
unnamed-30EXPLAIN select * from B where 6 = coalesce(5, 6)�
83+
84+
����#& ��(0���8@5SCAN(<,>) | FILTER @c6 EQUALS coalesce_int(@c10, @c6)�
85+
digraph G {
86+
fontname=courier;
87+
rankdir=BT;
88+
splines=polyline;
89+
1 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE @c6 EQUALS coalesce_int(@c10, @c6)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
90+
2 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Scan</td></tr><tr><td align="left">range: &lt;-∞, ∞&gt;</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
91+
3 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Primary Storage</td></tr><tr><td align="left">record types: [B]</td></tr></table>> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(INT AS B1, )" ];
92+
3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
93+
2 -> 1 [ label=<&nbsp;q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
94+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
unnamed-3:
2+
- query: EXPLAIN select * from B where 6L = coalesce(5L, 6L)
3+
explain: SCAN(<,>) | FILTER @c6 EQUALS coalesce_long(@c10, @c6)
4+
task_count: 155
5+
task_total_time_ms: 74
6+
transform_count: 38
7+
transform_time_ms: 51
8+
transform_yield_count: 14
9+
insert_time_ms: 5
10+
insert_new_count: 14
11+
insert_reused_count: 2
12+
- query: EXPLAIN select * from B where 6L = coalesce(5I, 6I)
13+
explain: SCAN(<,>) | FILTER @c6 EQUALS promote(coalesce_int(@c10, @c12) AS LONG)
14+
task_count: 155
15+
task_total_time_ms: 75
16+
transform_count: 38
17+
transform_time_ms: 52
18+
transform_yield_count: 14
19+
insert_time_ms: 3
20+
insert_new_count: 14
21+
insert_reused_count: 2
22+
- query: EXPLAIN select * from B where 6L = coalesce(5, 6)
23+
explain: SCAN(<,>) | FILTER @c6 EQUALS promote(coalesce_int(@c10, @c12) AS LONG)
24+
task_count: 155
25+
task_total_time_ms: 74
26+
transform_count: 38
27+
transform_time_ms: 51
28+
transform_yield_count: 14
29+
insert_time_ms: 4
30+
insert_new_count: 14
31+
insert_reused_count: 2
32+
- query: EXPLAIN select * from B where 6 = coalesce(5L, 6)
33+
explain: SCAN(<,>) | FILTER promote(@c6 AS LONG) EQUALS coalesce_long(@c10, promote(@c6
34+
AS LONG))
35+
task_count: 155
36+
task_total_time_ms: 74
37+
transform_count: 38
38+
transform_time_ms: 52
39+
transform_yield_count: 14
40+
insert_time_ms: 5
41+
insert_new_count: 14
42+
insert_reused_count: 2
43+
- query: EXPLAIN select * from B where 6I = coalesce(5L, 6I)
44+
explain: SCAN(<,>) | FILTER promote(@c6 AS LONG) EQUALS coalesce_long(@c10, promote(@c6
45+
AS LONG))
46+
task_count: 155
47+
task_total_time_ms: 74
48+
transform_count: 38
49+
transform_time_ms: 54
50+
transform_yield_count: 14
51+
insert_time_ms: 4
52+
insert_new_count: 14
53+
insert_reused_count: 2
54+
- query: EXPLAIN select * from B where 6i = coalesce(5l, 6i)
55+
explain: SCAN(<,>) | FILTER promote(@c6 AS LONG) EQUALS coalesce_long(@c10, promote(@c6
56+
AS LONG))
57+
task_count: 155
58+
task_total_time_ms: 74
59+
transform_count: 38
60+
transform_time_ms: 53
61+
transform_yield_count: 14
62+
insert_time_ms: 3
63+
insert_new_count: 14
64+
insert_reused_count: 2
65+
- query: EXPLAIN select * from B where 6 = coalesce(5, 6)
66+
explain: SCAN(<,>) | FILTER @c6 EQUALS coalesce_int(@c10, @c6)
67+
task_count: 155
68+
task_total_time_ms: 74
69+
transform_count: 38
70+
transform_time_ms: 52
71+
transform_yield_count: 14
72+
insert_time_ms: 4
73+
insert_new_count: 14
74+
insert_reused_count: 2

0 commit comments

Comments
 (0)