@sap/cds-compiler 2.10.4 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -0
- package/bin/.eslintrc.json +1 -2
- package/bin/cds_update_identifiers.js +10 -8
- package/bin/cdsc.js +58 -35
- package/bin/cdsse.js +1 -0
- package/bin/cdsv2m.js +3 -2
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +16 -0
- package/lib/api/.eslintrc.json +2 -0
- package/lib/api/main.js +10 -36
- package/lib/api/options.js +17 -8
- package/lib/api/validate.js +30 -3
- package/lib/backends.js +12 -13
- package/lib/base/dictionaries.js +2 -1
- package/lib/base/keywords.js +3 -2
- package/lib/base/message-registry.js +64 -11
- package/lib/base/messages.js +38 -18
- package/lib/base/model.js +6 -4
- package/lib/base/optionProcessorHelper.js +148 -86
- package/lib/checks/.eslintrc.json +2 -0
- package/lib/checks/actionsFunctions.js +2 -1
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/foreignKeys.js +4 -4
- package/lib/checks/managedInType.js +4 -4
- package/lib/checks/queryNoDbArtifacts.js +1 -3
- package/lib/checks/selectItems.js +4 -0
- package/lib/checks/sql-snippets.js +93 -0
- package/lib/checks/unknownMagic.js +6 -3
- package/lib/checks/validator.js +8 -0
- package/lib/compiler/assert-consistency.js +14 -5
- package/lib/compiler/base.js +64 -0
- package/lib/compiler/builtins.js +62 -16
- package/lib/compiler/checks.js +34 -10
- package/lib/compiler/definer.js +91 -112
- package/lib/compiler/index.js +30 -30
- package/lib/compiler/propagator.js +8 -4
- package/lib/compiler/resolver.js +279 -63
- package/lib/compiler/shared.js +65 -230
- package/lib/compiler/utils.js +191 -0
- package/lib/edm/annotations/genericTranslation.js +35 -18
- package/lib/edm/annotations/preprocessAnnotations.js +1 -1
- package/lib/edm/csn2edm.js +4 -3
- package/lib/edm/edm.js +8 -8
- package/lib/edm/edmPreprocessor.js +61 -59
- package/lib/edm/edmUtils.js +14 -15
- package/lib/gen/Dictionary.json +82 -40
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +19 -1
- package/lib/gen/language.tokens +80 -73
- package/lib/gen/languageLexer.interp +27 -1
- package/lib/gen/languageLexer.js +925 -826
- package/lib/gen/languageLexer.tokens +72 -65
- package/lib/gen/languageParser.js +4817 -4102
- package/lib/json/from-csn.js +57 -26
- package/lib/json/to-csn.js +244 -51
- package/lib/language/antlrParser.js +12 -1
- package/lib/language/docCommentParser.js +1 -1
- package/lib/language/errorStrategy.js +26 -8
- package/lib/language/genericAntlrParser.js +106 -30
- package/lib/language/language.g4 +200 -70
- package/lib/language/multiLineStringParser.js +536 -0
- package/lib/main.d.ts +220 -21
- package/lib/main.js +6 -3
- package/lib/model/api.js +2 -2
- package/lib/model/csnRefs.js +218 -86
- package/lib/model/csnUtils.js +99 -178
- package/lib/model/enrichCsn.js +84 -43
- package/lib/model/revealInternalProperties.js +25 -8
- package/lib/model/sortViews.js +8 -1
- package/lib/modelCompare/compare.js +2 -1
- package/lib/optionProcessor.js +33 -18
- package/lib/render/.eslintrc.json +1 -2
- package/lib/render/DuplicateChecker.js +2 -2
- package/lib/render/manageConstraints.js +1 -1
- package/lib/render/toCdl.js +202 -82
- package/lib/render/toHdbcds.js +194 -135
- package/lib/render/toRename.js +7 -10
- package/lib/render/toSql.js +91 -51
- package/lib/render/utils/common.js +24 -5
- package/lib/render/utils/sql.js +6 -4
- package/lib/transform/braceExpression.js +4 -2
- package/lib/transform/db/applyTransformations.js +189 -0
- package/lib/transform/db/associations.js +389 -0
- package/lib/transform/db/cdsPersistence.js +150 -0
- package/lib/transform/db/constraints.js +275 -119
- package/lib/transform/db/draft.js +6 -4
- package/lib/transform/db/expansion.js +10 -9
- package/lib/transform/db/flattening.js +23 -8
- package/lib/transform/db/temporal.js +236 -0
- package/lib/transform/db/transformExists.js +106 -25
- package/lib/transform/db/views.js +485 -0
- package/lib/transform/forHanaNew.js +90 -1036
- package/lib/transform/forOdataNew.js +11 -3
- package/lib/transform/localized.js +5 -14
- package/lib/transform/odata/generateForeignKeyElements.js +2 -2
- package/lib/transform/transformUtilsNew.js +34 -20
- package/lib/transform/translateAssocsToJoins.js +15 -23
- package/lib/transform/universalCsnEnricher.js +217 -47
- package/lib/utils/file.js +13 -6
- package/lib/utils/term.js +65 -42
- package/lib/utils/timetrace.js +55 -27
- package/package.json +1 -1
- package/lib/transform/db/helpers.js +0 -58
package/lib/language/language.g4
CHANGED
|
@@ -490,7 +490,7 @@ projectionSpec returns[ query ] locals[ src ]
|
|
|
490
490
|
// now a simplified `tableTerm`:
|
|
491
491
|
{
|
|
492
492
|
$src = { path: [], scope: 0 };
|
|
493
|
-
$query = { op: this.
|
|
493
|
+
$query = { op: this.valueWithTokenLocation( 'SELECT', $proj ), from: $src, location: this.startLocation() };
|
|
494
494
|
}
|
|
495
495
|
fromPath[ $src, 'artref']
|
|
496
496
|
( ':'
|
|
@@ -498,6 +498,8 @@ projectionSpec returns[ query ] locals[ src ]
|
|
|
498
498
|
fromPath[ $src, 'ref']
|
|
499
499
|
)?
|
|
500
500
|
( AS aliasName=ident['FromAlias'] { $src.name = $aliasName.id } )?
|
|
501
|
+
// ANTLR errors are better if we use ( A )? instead of ( A | ):
|
|
502
|
+
{ if (!$src.name) this.classifyImplicitName( $src.scope ? 'FromAlias' : 'Without' ); }
|
|
501
503
|
bracedSelectItemListDef[ $query ]?
|
|
502
504
|
excludingClause[ $query ]?
|
|
503
505
|
;
|
|
@@ -981,6 +983,7 @@ mixinElementDef[ outer ] locals[ art ]
|
|
|
981
983
|
|
|
982
984
|
misplacedAnnotations[ annos, messageId ]
|
|
983
985
|
:
|
|
986
|
+
// No docComment() here
|
|
984
987
|
annotationAssignment_ll1[ $annos ]+
|
|
985
988
|
{ if ($messageId) // issue specified in central registry
|
|
986
989
|
this.message( messageId, this.tokenLocation( $ctx.start, this.getCurrentToken() ) );
|
|
@@ -1076,7 +1079,7 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
1076
1079
|
annotationAssignment_ll1[ $annos ]*
|
|
1077
1080
|
requiredSemi // also req after foreign key spec
|
|
1078
1081
|
|
|
|
1079
|
-
l=LOCALIZED { $art.localized = this.
|
|
1082
|
+
l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
|
|
1080
1083
|
typeRefOptArgs[ $art ]
|
|
1081
1084
|
{ this.docComment( $annos ); }
|
|
1082
1085
|
annotationAssignment_ll1[ $annos ]*
|
|
@@ -1144,7 +1147,7 @@ selectItemDef[ outer ] locals[ annos = [] ]
|
|
|
1144
1147
|
@after{ if ($ctx.art) this.attachLocation($art.art); }
|
|
1145
1148
|
:
|
|
1146
1149
|
star='*'
|
|
1147
|
-
{ $outer.push( this.
|
|
1150
|
+
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1148
1151
|
|
|
|
1149
1152
|
{ this.docComment( $annos ); }
|
|
1150
1153
|
annotationAssignment_atn[ $annos ]*
|
|
@@ -1154,8 +1157,8 @@ selectItemDef[ outer ] locals[ annos = [] ]
|
|
|
1154
1157
|
key=KEY?
|
|
1155
1158
|
art=selectItemDefBody[ $outer, $annos ]
|
|
1156
1159
|
{
|
|
1157
|
-
if ($virtual) $art.art.virtual = this.
|
|
1158
|
-
if ($key) $art.art.key = this.
|
|
1160
|
+
if ($virtual) $art.art.virtual = this.valueWithTokenLocation( true, $virtual );
|
|
1161
|
+
if ($key) $art.art.key = this.valueWithTokenLocation( true, $key );
|
|
1159
1162
|
}
|
|
1160
1163
|
;
|
|
1161
1164
|
|
|
@@ -1188,7 +1191,7 @@ selectItemDefBody[ outer, annos ] returns[ art = {} ]
|
|
|
1188
1191
|
excludingClause[ $art ]?
|
|
1189
1192
|
|
|
|
1190
1193
|
star='*'
|
|
1191
|
-
{ $art.inline = [ this.
|
|
1194
|
+
{ $art.inline = [ this.valueWithTokenLocation( '*', $star ) ]; }
|
|
1192
1195
|
)
|
|
1193
1196
|
)?
|
|
1194
1197
|
|
|
|
@@ -1237,7 +1240,7 @@ selectItemInlineDef[ outer ] locals[ annos = [] ]
|
|
|
1237
1240
|
@after{ if ($ctx.art) this.attachLocation($art.art); }
|
|
1238
1241
|
:
|
|
1239
1242
|
star='*'
|
|
1240
|
-
{ $outer.push( this.
|
|
1243
|
+
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1241
1244
|
|
|
|
1242
1245
|
{ this.docComment( $annos ); }
|
|
1243
1246
|
annotationAssignment_atn[ $annos ]*
|
|
@@ -1298,15 +1301,17 @@ entityParameterDef[ outer ] locals[ art, annos = [] ]
|
|
|
1298
1301
|
annotationAssignment_fix[ $annos ]*
|
|
1299
1302
|
typeSpec[ $art ]
|
|
1300
1303
|
( DEFAULT expr=expression { $art.default = $expr.expr; } )?
|
|
1304
|
+
{ this.docComment( $annos ); }
|
|
1305
|
+
annotationAssignment_ll1[ $annos ]*
|
|
1301
1306
|
;
|
|
1302
1307
|
|
|
1303
1308
|
nullability[ art ]
|
|
1304
1309
|
:
|
|
1305
1310
|
not=NOT n1=NULL
|
|
1306
|
-
{ $art.notNull = this.
|
|
1311
|
+
{ $art.notNull = this.valueWithTokenLocation( true, $not, $n1 ); }
|
|
1307
1312
|
|
|
|
1308
1313
|
n2=NULL
|
|
1309
|
-
{ $art.notNull = this.
|
|
1314
|
+
{ $art.notNull = this.valueWithTokenLocation( false, $n2 ); }
|
|
1310
1315
|
;
|
|
1311
1316
|
|
|
1312
1317
|
elementProperties[ elem ]
|
|
@@ -1463,7 +1468,7 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1463
1468
|
{ this.docComment( $annos ); }
|
|
1464
1469
|
annotationAssignment_ll1[ $annos ]* requiredSemi
|
|
1465
1470
|
|
|
|
1466
|
-
l=LOCALIZED { $art.localized = this.
|
|
1471
|
+
l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
|
|
1467
1472
|
typeRefOptArgs[ $art ]
|
|
1468
1473
|
{ this.docComment( $annos ); }
|
|
1469
1474
|
annotationAssignment_ll1[ $annos ]*
|
|
@@ -1499,7 +1504,8 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1499
1504
|
{ $art.enum = Object.create(null); }
|
|
1500
1505
|
enumSymbolDef[ $art ]*
|
|
1501
1506
|
'}'
|
|
1502
|
-
optionalSemi
|
|
1507
|
+
optionalSemi
|
|
1508
|
+
| requiredSemi
|
|
1503
1509
|
)
|
|
1504
1510
|
|
|
|
1505
1511
|
':' // with element, e.g. `type T : E:elem enum { ... }`
|
|
@@ -1511,7 +1517,8 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1511
1517
|
{ $art.enum = Object.create(null); }
|
|
1512
1518
|
enumSymbolDef[ $art ]*
|
|
1513
1519
|
'}'
|
|
1514
|
-
optionalSemi
|
|
1520
|
+
optionalSemi
|
|
1521
|
+
| requiredSemi
|
|
1515
1522
|
)
|
|
1516
1523
|
|
|
|
1517
1524
|
{ this.docComment( $annos ); }
|
|
@@ -1520,7 +1527,8 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1520
1527
|
{ $art.enum = Object.create(null); }
|
|
1521
1528
|
enumSymbolDef[ $art ]*
|
|
1522
1529
|
'}'
|
|
1523
|
-
optionalSemi
|
|
1530
|
+
optionalSemi
|
|
1531
|
+
| requiredSemi
|
|
1524
1532
|
)
|
|
1525
1533
|
|
|
|
1526
1534
|
// TODO: complain if used in anno def?
|
|
@@ -1764,25 +1772,82 @@ orderByClause[ inQuery ] returns [ query ]
|
|
|
1764
1772
|
|
|
1765
1773
|
overOrderByClause returns [ expr ]
|
|
1766
1774
|
:
|
|
1767
|
-
o=ORDER b=BY { $expr = { op: this.
|
|
1775
|
+
o=ORDER b=BY { $expr = { op: this.valueWithTokenLocation( 'orderBy', $o, $b ) , args: [] }}
|
|
1768
1776
|
ob1=orderBySpec { $expr.args.push( $ob1.ob ); }
|
|
1769
1777
|
( ',' obn=orderBySpec { $expr.args.push( $obn.ob ); } )*
|
|
1770
1778
|
;
|
|
1771
1779
|
|
|
1772
1780
|
partitionByClause returns [ expr ]
|
|
1773
1781
|
:
|
|
1774
|
-
p=PARTITION b=BY { $expr = { op: this.
|
|
1782
|
+
p=PARTITION b=BY { $expr = { op: this.valueWithTokenLocation( 'partitionBy', $p, $b ) , args: [] }}
|
|
1775
1783
|
e1=expression { $expr.args.push( $e1.expr ); }
|
|
1776
1784
|
( ',' en=expression { $expr.args.push( $en.expr ); } )*
|
|
1777
1785
|
;
|
|
1778
1786
|
|
|
1787
|
+
windowFrameClause returns [ wf ]
|
|
1788
|
+
:
|
|
1789
|
+
r=ROWS { $wf = { op: this.valueWithTokenLocation( 'rows', $r ) , args: [] }}
|
|
1790
|
+
wfe=windowFrameExtentSpec { $wf.args.push( $wfe.wfe ); }
|
|
1791
|
+
;
|
|
1792
|
+
|
|
1793
|
+
windowFrameExtentSpec returns[ wfe ]
|
|
1794
|
+
:
|
|
1795
|
+
{ $wfe = {} }
|
|
1796
|
+
windowFrameStartSpec [ $wfe ]
|
|
1797
|
+
|
|
|
1798
|
+
b=BETWEEN
|
|
1799
|
+
{ $wfe = { op: this.valueWithTokenLocation( 'frameBetween', $b ), args: [] } }
|
|
1800
|
+
wfb1=windowFrameBoundSpec { $wfe.args.push( $wfb1.wfb ); }
|
|
1801
|
+
AND
|
|
1802
|
+
wfb2=windowFrameBoundSpec { $wfe.args.push( $wfb2.wfb ); }
|
|
1803
|
+
;
|
|
1804
|
+
|
|
1805
|
+
windowFrameBoundSpec returns [ wfb ]
|
|
1806
|
+
@after{ /* #ATN 1 */ }
|
|
1807
|
+
:
|
|
1808
|
+
// #ATN: Not ll1 because `UNBOUNDED` could also be part of the windowFrameStartSpec
|
|
1809
|
+
// `UNBOUNDED` would then be immediately followed by `PRECEDING`
|
|
1810
|
+
u=UNBOUNDED f=FOLLOWING
|
|
1811
|
+
{ $wfb = { op: this.valueWithTokenLocation( 'unboundedFollowing', $u, $f ), args: []} }
|
|
1812
|
+
|
|
|
1813
|
+
// #ATN: Not ll1 because `Number` could also be part of the windowFrameStartSpec
|
|
1814
|
+
// `Number` would then be immediately followed by `PRECEDING`
|
|
1815
|
+
n=Number f=FOLLOWING
|
|
1816
|
+
{ $wfb = { op: this.valueWithTokenLocation( 'following', $n, $f ), args: [ this.numberLiteral( $n ) ]} }
|
|
1817
|
+
|
|
|
1818
|
+
{ $wfb = {} }
|
|
1819
|
+
windowFrameStartSpec [ $wfb ]
|
|
1820
|
+
;
|
|
1821
|
+
|
|
1822
|
+
windowFrameStartSpec [ wf ]
|
|
1823
|
+
:
|
|
1824
|
+
u=UNBOUNDED p=PRECEDING
|
|
1825
|
+
{
|
|
1826
|
+
$wf.op = this.valueWithTokenLocation( 'unboundedPreceding', $u, $p );
|
|
1827
|
+
$wf.args = [];
|
|
1828
|
+
}
|
|
1829
|
+
|
|
|
1830
|
+
n=Number p=PRECEDING
|
|
1831
|
+
{
|
|
1832
|
+
$wf.op = this.valueWithTokenLocation( 'preceding', $p );
|
|
1833
|
+
$wf.args = [ this.numberLiteral( $n ) ];
|
|
1834
|
+
}
|
|
1835
|
+
|
|
|
1836
|
+
c=CURRENT r=ROW
|
|
1837
|
+
{
|
|
1838
|
+
$wf.op = this.valueWithTokenLocation( 'currentRow', $c, $r );
|
|
1839
|
+
$wf.args = [];
|
|
1840
|
+
}
|
|
1841
|
+
;
|
|
1842
|
+
|
|
1779
1843
|
overClause returns [ over ]
|
|
1780
1844
|
@after { this.attachLocation($over); }
|
|
1781
1845
|
:
|
|
1782
|
-
o=OVER { $over = { op: this.
|
|
1846
|
+
o=OVER { $over = { op: this.valueWithTokenLocation( 'over', $o ) , args: [] } }
|
|
1783
1847
|
'('
|
|
1784
1848
|
( pb=partitionByClause { $over.args.push( $pb.expr ); } )?
|
|
1785
1849
|
( ob=overOrderByClause { $over.args.push( $ob.expr ); } )?
|
|
1850
|
+
( wf=windowFrameClause { $over.args.push( $wf.wf ); } )?
|
|
1786
1851
|
')'
|
|
1787
1852
|
;
|
|
1788
1853
|
|
|
@@ -1799,11 +1864,11 @@ limitClause[ inQuery ] returns [ query ]
|
|
|
1799
1864
|
orderBySpec returns[ ob ]
|
|
1800
1865
|
:
|
|
1801
1866
|
e=expression { $ob = $e.expr; }
|
|
1802
|
-
( asc=ASC { $ob.sort = this.
|
|
1803
|
-
| desc=DESC { $ob.sort = this.
|
|
1867
|
+
( asc=ASC { $ob.sort = this.valueWithTokenLocation( 'asc', $asc ); }
|
|
1868
|
+
| desc=DESC { $ob.sort = this.valueWithTokenLocation( 'desc', $desc ); }
|
|
1804
1869
|
)?
|
|
1805
1870
|
( nb=NULLS ne=( FIRST | LAST )
|
|
1806
|
-
{ $ob.nulls = this.
|
|
1871
|
+
{ $ob.nulls = this.valueWithTokenLocation( $ne.text.toLowerCase(), $nb, $ne ); }
|
|
1807
1872
|
)?
|
|
1808
1873
|
;
|
|
1809
1874
|
|
|
@@ -1826,7 +1891,7 @@ queryPrimary returns[ query = {} ]
|
|
|
1826
1891
|
{ $query = this.surroundByParens( $qe.query, $open, $close ); }
|
|
1827
1892
|
|
|
|
1828
1893
|
select=SELECT
|
|
1829
|
-
{ $query = { op: this.
|
|
1894
|
+
{ $query = { op: this.valueWithTokenLocation( 'SELECT', $select ), location: this.startLocation() }; }
|
|
1830
1895
|
(
|
|
1831
1896
|
FROM querySource[ $query ]
|
|
1832
1897
|
(
|
|
@@ -1835,13 +1900,13 @@ queryPrimary returns[ query = {} ]
|
|
|
1835
1900
|
'}' INTO
|
|
1836
1901
|
)?
|
|
1837
1902
|
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
1838
|
-
{ $query.quantifier = this.
|
|
1903
|
+
{ $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
|
|
1839
1904
|
)?
|
|
1840
1905
|
bracedSelectItemListDef[ $query ]?
|
|
1841
1906
|
excludingClause[ $query ]?
|
|
1842
1907
|
|
|
|
1843
1908
|
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
1844
|
-
{ $query.quantifier = this.
|
|
1909
|
+
{ $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
|
|
1845
1910
|
)?
|
|
1846
1911
|
{ $query.columns = []; } // set it early to avoid "wildcard" errors
|
|
1847
1912
|
selectItemDef[ $query.columns ]
|
|
@@ -1895,8 +1960,8 @@ joinOp[ left ] returns[ table ] locals [ join ]
|
|
|
1895
1960
|
| t1=RIGHT t2=OUTER? c=joinCardinality? op=JOIN { $join = 'right' }
|
|
1896
1961
|
| t1=FULL t2=OUTER? c=joinCardinality? op=JOIN { $join = 'full' }
|
|
1897
1962
|
)
|
|
1898
|
-
{ $table = { op: this.
|
|
1899
|
-
join: this.
|
|
1963
|
+
{ $table = { op: this.valueWithTokenLocation( 'join', $op ),
|
|
1964
|
+
join: this.valueWithTokenLocation( $join, $t1 || $op, $t2 ),
|
|
1900
1965
|
args: ($left ? [$left] : []),
|
|
1901
1966
|
location: $left && $left.location };
|
|
1902
1967
|
if ($ctx.c) $table.cardinality = $c.joinCard; }
|
|
@@ -1948,6 +2013,8 @@ tableTerm returns [ table ]
|
|
|
1948
2013
|
// if we would use rule `ident`, we would either had to make all JOIN
|
|
1949
2014
|
// kinds reserved or introduce ATN
|
|
1950
2015
|
)?
|
|
2016
|
+
// ANTLR errors are better if we use ( A | B )? instead of ( A | B | ):
|
|
2017
|
+
{ if (!$table.name) this.classifyImplicitName( $table.scope ? 'FromAlias' : 'Without' ); }
|
|
1951
2018
|
|
|
|
1952
2019
|
open='('
|
|
1953
2020
|
// #ATN: The following alternative is not LL1, because both can start with
|
|
@@ -2001,24 +2068,24 @@ fromPath[ qp, idkind ]
|
|
|
2001
2068
|
|
|
2002
2069
|
condition returns [ cond ] locals [ args = [], orl = [] ]
|
|
2003
2070
|
@after{
|
|
2004
|
-
$cond = ($args.length
|
|
2071
|
+
$cond = ($args.length === 1)
|
|
2005
2072
|
? this.attachLocation( $args[0] )
|
|
2006
2073
|
: this.attachLocation({ op: $orl[0], args: $args });
|
|
2007
2074
|
}
|
|
2008
2075
|
:
|
|
2009
2076
|
c1=conditionAnd { $args.push($c1.cond); }
|
|
2010
|
-
( or=OR c2=conditionAnd { $args.push($c2.cond); $orl.push(this.
|
|
2077
|
+
( or=OR c2=conditionAnd { $args.push($c2.cond); $orl.push(this.valueWithTokenLocation( 'or', $or ))} )*
|
|
2011
2078
|
;
|
|
2012
2079
|
|
|
2013
2080
|
conditionAnd returns [ cond ] locals [ args = [], andl = [] ]
|
|
2014
2081
|
@after{
|
|
2015
|
-
$cond = ($args.length
|
|
2082
|
+
$cond = ($args.length === 1)
|
|
2016
2083
|
? $args[0]
|
|
2017
2084
|
: this.attachLocation({ op: $andl[0], args: $args });
|
|
2018
2085
|
}
|
|
2019
2086
|
:
|
|
2020
2087
|
c1=conditionTerm { $args.push($c1.cond); }
|
|
2021
|
-
( and=AND c2=conditionTerm { $args.push($c2.cond); $andl.push(this.
|
|
2088
|
+
( and=AND c2=conditionTerm { $args.push($c2.cond); $andl.push(this.valueWithTokenLocation( 'and', $and )) } )*
|
|
2022
2089
|
;
|
|
2023
2090
|
|
|
2024
2091
|
conditionTerm returns [ cond ]
|
|
@@ -2027,38 +2094,38 @@ conditionTerm returns [ cond ]
|
|
|
2027
2094
|
}
|
|
2028
2095
|
:
|
|
2029
2096
|
nt=NOT ct=conditionTerm
|
|
2030
|
-
{ $cond = { op: this.
|
|
2097
|
+
{ $cond = { op: this.valueWithTokenLocation( 'not', $nt ), args: [ $ct.cond ] }; }
|
|
2031
2098
|
|
|
|
2032
2099
|
ex=EXISTS
|
|
2033
2100
|
(
|
|
2034
2101
|
open='(' qe=queryExpression close=')'
|
|
2035
|
-
{ $cond = { op: this.
|
|
2102
|
+
{ $cond = { op: this.valueWithTokenLocation( 'exists', $ex ),
|
|
2036
2103
|
args: [ this.surroundByParens( $qe.query, $open, $close, true ) ] }; }
|
|
2037
2104
|
|
|
|
2038
2105
|
qm=( HideAlternatives | '?' )
|
|
2039
|
-
{ $cond = { op: this.
|
|
2040
|
-
{ param: this.
|
|
2106
|
+
{ $cond = { op: this.valueWithTokenLocation( 'exists', $ex ), args: [
|
|
2107
|
+
{ param: this.valueWithTokenLocation( '?', $qm ), scope: 'param' }
|
|
2041
2108
|
] };
|
|
2042
2109
|
this.csnParseOnly( 'Dynamic parameter "?" is not supported', $qm );
|
|
2043
2110
|
}
|
|
2044
2111
|
|
|
|
2045
2112
|
ep=valuePath[ 'ref' ]
|
|
2046
2113
|
{ $ep.qp['$'+'expected'] = 'exists';
|
|
2047
|
-
$cond = { op: this.
|
|
2114
|
+
$cond = { op: this.valueWithTokenLocation( 'exists', $ex ), args: [ $ep.qp ] };
|
|
2048
2115
|
}
|
|
2049
2116
|
)
|
|
2050
2117
|
|
|
|
2051
2118
|
expr=expression // see @after
|
|
2052
2119
|
(
|
|
2053
2120
|
rel=( '=' | '<>' | '>' | '>=' | '<' | '<=' | '!=' )
|
|
2054
|
-
{ $cond = { op: this.
|
|
2121
|
+
{ $cond = { op: this.valueWithTokenLocation( $rel.text, $rel ), args: [ $expr.expr ] }; }
|
|
2055
2122
|
( asa=( ANY | SOME | ALL )
|
|
2056
|
-
{ $cond.quantifier = this.
|
|
2123
|
+
{ $cond.quantifier = this.valueWithTokenLocation( $asa.text.toLowerCase(), $asa ); }
|
|
2057
2124
|
)?
|
|
2058
2125
|
e2=expression { $cond.args.push($e2.expr); }
|
|
2059
2126
|
|
|
|
2060
2127
|
IS ( inn=NOT NULL | innu=NULL )
|
|
2061
|
-
{ $cond = { op: $inn ? this.
|
|
2128
|
+
{ $cond = { op: $inn ? this.valueWithTokenLocation( 'isNotNull', $inn ) : this.valueWithTokenLocation( 'isNull', $innu ), args: [ $expr.expr ] }; }
|
|
2062
2129
|
|
|
|
2063
2130
|
{ $cond = { args: [ $expr.expr ] }; }
|
|
2064
2131
|
NOT predicate[ $cond, true ]
|
|
@@ -2074,14 +2141,14 @@ predicate[ cond, negated ]
|
|
|
2074
2141
|
// NOT (a BETWEEN b AND c)
|
|
2075
2142
|
:
|
|
2076
2143
|
ino=IN e1=expression // including ExpressionList
|
|
2077
|
-
{ $cond.op = this.
|
|
2144
|
+
{ $cond.op = this.valueWithTokenLocation( (negated) ? 'notIn' : 'in', $ino ); $cond.args.push( $e1.expr ); }
|
|
2078
2145
|
|
|
|
2079
2146
|
bw=BETWEEN e2=expression
|
|
2080
|
-
{ $cond.op = this.
|
|
2147
|
+
{ $cond.op = this.valueWithTokenLocation( (negated) ? 'notBetween' : 'between', $bw ); $cond.args.push( $e2.expr ); }
|
|
2081
2148
|
AND e3=expression { $cond.args.push( $e3.expr ); }
|
|
2082
2149
|
|
|
|
2083
2150
|
lk=LIKE e4=expression
|
|
2084
|
-
{ $cond.op = this.
|
|
2151
|
+
{ $cond.op = this.valueWithTokenLocation( (negated) ? 'notLike' : 'like', $lk ); $cond.args.push( $e4.expr ); }
|
|
2085
2152
|
( ESCAPE e5=expression { $cond.args.push( $e5.expr ); } )?
|
|
2086
2153
|
;
|
|
2087
2154
|
|
|
@@ -2093,7 +2160,7 @@ expression returns [ expr ]
|
|
|
2093
2160
|
or='||' e2=expressionSum
|
|
2094
2161
|
{
|
|
2095
2162
|
$expr = {
|
|
2096
|
-
op: this.
|
|
2163
|
+
op: this.valueWithTokenLocation( '||', $or ), args: [$expr, $e2.expr],
|
|
2097
2164
|
location: this.combinedLocation( $expr, $e2.expr ) };
|
|
2098
2165
|
}
|
|
2099
2166
|
)*
|
|
@@ -2107,7 +2174,7 @@ expressionSum returns [ expr ]
|
|
|
2107
2174
|
op=( '+' | '-' ) e2=expressionFactor
|
|
2108
2175
|
{
|
|
2109
2176
|
$expr = {
|
|
2110
|
-
op: this.
|
|
2177
|
+
op: this.valueWithTokenLocation( $op.text, $op ), args: [$expr, $e2.expr],
|
|
2111
2178
|
location: this.combinedLocation( $expr, $e2.expr ) };
|
|
2112
2179
|
}
|
|
2113
2180
|
)*
|
|
@@ -2121,7 +2188,7 @@ expressionFactor returns [ expr ]
|
|
|
2121
2188
|
op=( '*' | '/' ) e2=expressionTerm
|
|
2122
2189
|
{
|
|
2123
2190
|
$expr = {
|
|
2124
|
-
op: this.
|
|
2191
|
+
op: this.valueWithTokenLocation( $op.text, $op ), args: [$expr, $e2.expr],
|
|
2125
2192
|
location: this.combinedLocation( $expr, $e2.expr ) };
|
|
2126
2193
|
}
|
|
2127
2194
|
)*
|
|
@@ -2141,7 +2208,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2141
2208
|
{ $expr = $sf.ret; }
|
|
2142
2209
|
|
|
|
2143
2210
|
ca=CASE
|
|
2144
|
-
{ $expr = { op : this.
|
|
2211
|
+
{ $expr = { op : this.valueWithTokenLocation( 'case', $ca ), args: [] }; }
|
|
2145
2212
|
(
|
|
2146
2213
|
e2=expression { $expr.args.push($e2.expr); }
|
|
2147
2214
|
( ow=WHEN ew=expression THEN e3=expression
|
|
@@ -2159,7 +2226,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2159
2226
|
|
|
|
2160
2227
|
ne=NEW nqp=valuePath[ 'ref', null] // token rewrite for NEW
|
|
2161
2228
|
// please note: there will be no compiler-supported code completion after NEW
|
|
2162
|
-
{ $expr = { op: this.
|
|
2229
|
+
{ $expr = { op: this.valueWithTokenLocation( 'new', $ne ), args: [] };
|
|
2163
2230
|
this.notSupportedYet( $ne ); }
|
|
2164
2231
|
|
|
|
2165
2232
|
vp=valuePath[ 'ref', null ] { $expr = this.valuePathAst( $vp.qp ); }
|
|
@@ -2178,7 +2245,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2178
2245
|
)
|
|
2179
2246
|
|
|
|
2180
2247
|
qm=( HideAlternatives | '?' )
|
|
2181
|
-
{ $expr = { param: this.
|
|
2248
|
+
{ $expr = { param: this.valueWithTokenLocation( '?', $qm ), scope: 'param' };
|
|
2182
2249
|
this.csnParseOnly( 'Dynamic parameter "?" is not supported', $qm );
|
|
2183
2250
|
}
|
|
2184
2251
|
|
|
|
@@ -2196,7 +2263,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2196
2263
|
close=')'
|
|
2197
2264
|
{
|
|
2198
2265
|
if ($expr.length > 1)
|
|
2199
|
-
$expr = { op: this.
|
|
2266
|
+
$expr = { op: this.valueWithTokenLocation( ',', $open ), args: $expr };
|
|
2200
2267
|
else if ($expr[0]) // can be `null` if condition failed to parse
|
|
2201
2268
|
$expr = this.surroundByParens( $expr[0], $open, $close );
|
|
2202
2269
|
}
|
|
@@ -2236,7 +2303,7 @@ specialFunction returns [ ret = { } ] locals[ art = {} ]
|
|
|
2236
2303
|
ca=CAST open='('
|
|
2237
2304
|
{
|
|
2238
2305
|
$ret = {
|
|
2239
|
-
op: this.
|
|
2306
|
+
op: this.valueWithTokenLocation( 'cast', $ca ),
|
|
2240
2307
|
args: [ ],
|
|
2241
2308
|
location: this.tokenLocation( $ca )
|
|
2242
2309
|
};
|
|
@@ -2306,15 +2373,15 @@ pathArguments[ pathStep, considerSpecial ]
|
|
|
2306
2373
|
funcExpression[ $pathStep, $considerSpecial ]
|
|
2307
2374
|
)*
|
|
2308
2375
|
|
|
|
2309
|
-
a=ALL { $pathStep.quantifier = this.
|
|
2376
|
+
a=ALL { $pathStep.quantifier = this.valueWithTokenLocation( 'all', $a ); }
|
|
2310
2377
|
e1=expression { $pathStep.args = [ $e1.expr ]; }
|
|
2311
2378
|
|
|
|
2312
|
-
d=DISTINCT { $pathStep.quantifier = this.
|
|
2379
|
+
d=DISTINCT { $pathStep.quantifier = this.valueWithTokenLocation( 'distinct', $d ); }
|
|
2313
2380
|
e1=expression { $pathStep.args = [ $e1.expr ]; }
|
|
2314
2381
|
( ',' e2=expression { $pathStep.args.push( $e2.expr ); } )*
|
|
2315
2382
|
|
|
|
2316
2383
|
star='*'
|
|
2317
|
-
{ $pathStep.args = [ { location: this.tokenLocation($star), val: '*', literal: 'token' } ]; }
|
|
2384
|
+
{ $pathStep.args = [ { location: this.tokenLocation( $star ), val: '*', literal: 'token' } ]; }
|
|
2318
2385
|
|
|
|
2319
2386
|
{ $pathStep.args = []; }
|
|
2320
2387
|
)
|
|
@@ -2388,7 +2455,7 @@ optionalWhereForFilter
|
|
|
2388
2455
|
|
|
2389
2456
|
// Simple paths and values ---------------------------------------------------
|
|
2390
2457
|
|
|
2391
|
-
annoValueBase returns[ val ] locals [
|
|
2458
|
+
annoValueBase returns[ val ] locals [ seenEllipsis = false ]
|
|
2392
2459
|
@after { this.attachLocation($val); }
|
|
2393
2460
|
:
|
|
2394
2461
|
{ $val = { literal: 'struct', location: this.startLocation() }; }
|
|
@@ -2408,30 +2475,43 @@ annoValueBase returns[ val ] locals [ hasEllipsis=0 ]
|
|
|
2408
2475
|
'['
|
|
2409
2476
|
(
|
|
2410
2477
|
(
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2478
|
+
head=arrayValue { $val.val.push( $head.val ); }
|
|
2479
|
+
|
|
|
2480
|
+
e='...' ( UP TO upTo=arrayValue )?
|
|
2481
|
+
{{
|
|
2482
|
+
const item = { literal: 'token', val: '...', location: this.tokenLocation($e) };
|
|
2483
|
+
$val.val.push( item );
|
|
2484
|
+
if ($ctx.upTo) item.upTo = $upTo.val;
|
|
2485
|
+
$seenEllipsis = !$ctx.upTo || 'upTo';
|
|
2486
|
+
}}
|
|
2418
2487
|
)
|
|
2419
2488
|
(
|
|
2420
2489
|
',' { if (this.isStraightBefore(']')) break; } // allow ',' before ']'
|
|
2421
2490
|
(
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2491
|
+
tail=arrayValue { $val.val.push( $tail.val ); }
|
|
2492
|
+
|
|
|
2493
|
+
{ $ctx.upTo = null; } // is not reset
|
|
2494
|
+
e='...' ( UP TO upTo=arrayValue )?
|
|
2495
|
+
{{
|
|
2496
|
+
const item = { literal: 'token', val: '...', location: this.tokenLocation($e) };
|
|
2497
|
+
if ($ctx.upTo) item.upTo = $upTo.val;
|
|
2498
|
+
$val.val.push( item );
|
|
2499
|
+
if ($seenEllipsis === true) // TODO: adapt msg to UP TO
|
|
2500
|
+
this.error( 'syntax-unexpected-ellipsis', $e, { code: '...' },
|
|
2501
|
+
'Expected no more than one $(CODE)' );
|
|
2502
|
+
else
|
|
2503
|
+
$seenEllipsis = !$ctx.upTo || 'upTo';
|
|
2504
|
+
}}
|
|
2431
2505
|
)
|
|
2432
2506
|
)*
|
|
2433
2507
|
)?
|
|
2434
|
-
']'
|
|
2508
|
+
cb=']'
|
|
2509
|
+
{
|
|
2510
|
+
if ($seenEllipsis === 'upTo')
|
|
2511
|
+
this.error( 'syntax-expecting-ellipsis', $cb, // at closing bracket
|
|
2512
|
+
{ code: '... up to', newcode: '...' },
|
|
2513
|
+
'Expecting an array item $(NEWCODE) after an item with $(CODE)' );
|
|
2514
|
+
}
|
|
2435
2515
|
|
|
|
2436
2516
|
v1=literalValue { $val = $v1.val; }
|
|
2437
2517
|
|
|
|
@@ -2602,6 +2682,7 @@ ident[ category ] returns[ id ]
|
|
|
2602
2682
|
| COMPOSITION
|
|
2603
2683
|
| CONTEXT
|
|
2604
2684
|
| CROSS
|
|
2685
|
+
| CURRENT
|
|
2605
2686
|
| DAY
|
|
2606
2687
|
| DEFAULT
|
|
2607
2688
|
| DEFINE
|
|
@@ -2619,6 +2700,7 @@ ident[ category ] returns[ id ]
|
|
|
2619
2700
|
| EXTEND
|
|
2620
2701
|
| FIRST
|
|
2621
2702
|
| FLOATING
|
|
2703
|
+
| FOLLOWING
|
|
2622
2704
|
| FULL
|
|
2623
2705
|
| FUNCTION
|
|
2624
2706
|
| GROUP
|
|
@@ -2650,18 +2732,23 @@ ident[ category ] returns[ id ]
|
|
|
2650
2732
|
| OUTER
|
|
2651
2733
|
| PARAMETERS
|
|
2652
2734
|
| PARTITION
|
|
2735
|
+
| PRECEDING
|
|
2653
2736
|
| PROJECTION
|
|
2654
2737
|
| REDIRECTED
|
|
2655
2738
|
| RETURNS
|
|
2656
2739
|
| RIGHT
|
|
2740
|
+
| ROW
|
|
2741
|
+
| ROWS
|
|
2657
2742
|
| SECOND
|
|
2658
2743
|
| SERVICE
|
|
2659
2744
|
| THEN
|
|
2660
2745
|
| TRAILING
|
|
2661
2746
|
| UNION
|
|
2747
|
+
| UP
|
|
2662
2748
|
| TO
|
|
2663
2749
|
| TYPE
|
|
2664
2750
|
| USING
|
|
2751
|
+
| UNBOUNDED
|
|
2665
2752
|
| VARIABLE
|
|
2666
2753
|
| VIEW
|
|
2667
2754
|
| YEAR
|
|
@@ -2682,9 +2769,40 @@ LineComment : '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN);
|
|
|
2682
2769
|
|
|
2683
2770
|
// Values --------------------------------------------------------------------
|
|
2684
2771
|
|
|
2685
|
-
|
|
2772
|
+
// for syntactic code-completion: Combine all three string styles
|
|
2773
|
+
// Note: Use rule `string` instead as that also parses escape sequences!
|
|
2774
|
+
String : SingleLineString
|
|
2775
|
+
| MultiLineString
|
|
2776
|
+
| MutlLineStringBlock;
|
|
2777
|
+
|
|
2778
|
+
fragment SingleLineString
|
|
2686
2779
|
:
|
|
2687
|
-
|
|
2780
|
+
// \u0027 = '\''
|
|
2781
|
+
// \u2028 = LS (Line Separator)
|
|
2782
|
+
// \u2029 = PS (Paragraph Separator)
|
|
2783
|
+
( '\'' ~[\u0027\n\r\u2028\u2029]* '\'' )+ //
|
|
2784
|
+
;
|
|
2785
|
+
|
|
2786
|
+
fragment MultiLineString
|
|
2787
|
+
:
|
|
2788
|
+
('`' ( MultiLineStringContentChar | EscapeSequence )* '`' )
|
|
2789
|
+
;
|
|
2790
|
+
|
|
2791
|
+
fragment MutlLineStringBlock
|
|
2792
|
+
:
|
|
2793
|
+
('```' ( MultiLineStringContentChar | EscapeSequence )* '```')
|
|
2794
|
+
;
|
|
2795
|
+
|
|
2796
|
+
fragment EscapeSequence
|
|
2797
|
+
:
|
|
2798
|
+
// we could list each escape sequence explicitly, but we already
|
|
2799
|
+
// decode them in genericAntlrParser.js, so no need to do work twice.
|
|
2800
|
+
'\\' .
|
|
2801
|
+
;
|
|
2802
|
+
|
|
2803
|
+
fragment MultiLineStringContentChar
|
|
2804
|
+
:
|
|
2805
|
+
(~[\u0060\\]) // \u0060 = '`'
|
|
2688
2806
|
;
|
|
2689
2807
|
|
|
2690
2808
|
QuotedLiteral
|
|
@@ -2693,10 +2811,15 @@ QuotedLiteral
|
|
|
2693
2811
|
( '\'' ~[\u0027\n\r\u2028\u2029]* '\'' )+ // \u0027 = '\''
|
|
2694
2812
|
;
|
|
2695
2813
|
|
|
2814
|
+
// This literal improves error messages for unterminated literals.
|
|
2696
2815
|
UnterminatedLiteral
|
|
2697
2816
|
:
|
|
2698
2817
|
( [xX] | [dD][aA][tT][eE] | [tT][iI][mM][eE] ( [sS][tT][aA][mM][pP] )? )?
|
|
2699
2818
|
'\'' ~[\u0027\n\r\u2028\u2029]* // \u0027 = '\''
|
|
2819
|
+
|
|
|
2820
|
+
('`' ( MultiLineStringContentChar | EscapeSequence )* )
|
|
2821
|
+
|
|
|
2822
|
+
('```' ( MultiLineStringContentChar | EscapeSequence )* )
|
|
2700
2823
|
;
|
|
2701
2824
|
|
|
2702
2825
|
UnterminatedDelimitedIdentifier
|
|
@@ -2763,6 +2886,7 @@ BOTH : [bB][oO][tT][hH] ;
|
|
|
2763
2886
|
COMPOSITION : [cC][oO][mM][pP][oO][sS][iI][tT][iI][oO][nN] ;
|
|
2764
2887
|
CONTEXT : [cC][oO][nN][tT][eE][xX][tT] ;
|
|
2765
2888
|
CROSS : [cC][rR][oO][sS][sS] ;
|
|
2889
|
+
CURRENT : [cC][uU][rR][rR][eE][nN][tT] ;
|
|
2766
2890
|
DAY : [dD][aA][yY] ;
|
|
2767
2891
|
DEFAULT : [dD][eE][fF][aA][uU][lL][tT] ;
|
|
2768
2892
|
DEFINE : [dD][eE][fF][iI][nN][eE] ;
|
|
@@ -2780,6 +2904,7 @@ EXCLUDING : [eE][xX][cC][lL][uU][dD][iI][nN][gG] ;
|
|
|
2780
2904
|
EXTEND : [eE][xX][tT][eE][nN][dD] ;
|
|
2781
2905
|
FIRST : [fF][iI][rR][sS][tT] ;
|
|
2782
2906
|
FLOATING : [fF][lL][oO][aA][tT][iI][nN][gG] ;
|
|
2907
|
+
FOLLOWING : [fF][oO][lL][lL][oO][wW][iI][nN][gG] ;
|
|
2783
2908
|
FULL : [fF][uU][lL][lL] ;
|
|
2784
2909
|
FUNCTION : [fF][uU][nN][cC][tT][iI][oO][nN] ;
|
|
2785
2910
|
GROUP : [gG][rR][oO][uU][pP] ;
|
|
@@ -2812,10 +2937,13 @@ OUTER : [oO][uU][tT][eE][rR] ;
|
|
|
2812
2937
|
// OVER : [oO][vV][eE][rR] ;
|
|
2813
2938
|
PARAMETERS : [pP][aA][rR][aA][mM][eE][tT][eE][rR][sS] ;
|
|
2814
2939
|
PARTITION: [pP][aA][rR][tT][iI][tT][iI][oO][nN] ;
|
|
2940
|
+
PRECEDING: [pP][rR][eE][cC][eE][dD][iI][nN][gG] ;
|
|
2815
2941
|
PROJECTION : [pP][rR][oO][jJ][eE][cC][tT][iI][oO][nN] ;
|
|
2816
2942
|
REDIRECTED : [rR][eE][dD][iI][rR][eE][cC][tT][eE][dD] ;
|
|
2817
2943
|
RETURNS : [rR][eE][tT][uU][rR][nN][sS] ;
|
|
2818
2944
|
RIGHT : [rR][iI][gG][hH][tT] ;
|
|
2945
|
+
ROW : [rR][oO][wW] ;
|
|
2946
|
+
ROWS : [rR][oO][wW][sS] ;
|
|
2819
2947
|
SECOND : [sS][eE][cC][oO][nN][dD] ;
|
|
2820
2948
|
SERVICE : [sS][eE][rR][vV][iI][cC][eE] ;
|
|
2821
2949
|
THEN : [tT][hH][eE][nN] ;
|
|
@@ -2823,6 +2951,8 @@ TRAILING : [tT][rR][aA][iI][lL][iI][nN][gG] ;
|
|
|
2823
2951
|
TO : [tT][oO] ; // or make reserved? (is in SQL-92)
|
|
2824
2952
|
TYPE : [tT][yY][pP][eE] ;
|
|
2825
2953
|
UNION : [uU][nN][iI][oO][nN] ;
|
|
2954
|
+
UNBOUNDED : [uU][nN][bB][oO][uU][nN][dD][eE][dD] ;
|
|
2955
|
+
UP : [uU][pP] ;
|
|
2826
2956
|
USING : [uU][sS][iI][nN][gG] ;
|
|
2827
2957
|
VARIABLE : [vV][aA][rR][iI][aA][bB][lL][eE] ;
|
|
2828
2958
|
VIEW : [vV][iI][eE][wW] ;
|