Unverified 提交 6801c1e5 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1768 from katzyn/misc

Add more context-sensitive keywords
......@@ -490,8 +490,14 @@ The following tokens are keywords in H2:
<tbody>
<tr><td>ALL</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>AND</td>
<td>CS</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>ARRAY</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td></td></tr>
<tr><td>AS</td>
<td>CS</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>BETWEEN</td>
<td>CS</td><td>+</td><td>+</td><td>+</td><td>NR</td><td>+</td></tr>
<tr><td>CASE</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>CHECK</td>
......@@ -518,6 +524,8 @@ The following tokens are keywords in H2:
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>FETCH</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>FILTER</td>
<td>CS</td><td>+</td><td>+</td><td>+</td><td></td><td></td></tr>
<tr><td>FOR</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>FOREIGN</td>
......@@ -532,6 +540,10 @@ The following tokens are keywords in H2:
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>IF</td>
<td>+</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>ILIKE</td>
<td>CS</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>IN</td>
<td>CS</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>INNER</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>INTERSECT</td>
......@@ -544,10 +556,12 @@ The following tokens are keywords in H2:
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>JOIN</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>LEFT</td>
<td>CS</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>LIKE</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>LIMIT</td>
<td>+</td><td>NR</td><td>NR</td><td></td><td>+</td><td></td></tr>
<td>+</td><td></td><td></td><td></td><td>+</td><td></td></tr>
<tr><td>LOCALTIME</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td></td></tr>
<tr><td>LOCALTIMESTAMP</td>
......@@ -564,12 +578,20 @@ The following tokens are keywords in H2:
<td>+</td><td>+</td><td>+</td><td></td><td></td><td></td></tr>
<tr><td>ON</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>OR</td>
<td>CS</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>ORDER</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>OVER</td>
<td>CS</td><td>+</td><td>+</td><td>+</td><td></td><td></td></tr>
<tr><td>PRIMARY</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>QUALIFY</td>
<td>+</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>REGEXP</td>
<td>CS</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>RIGHT</td>
<td>CS</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>ROW</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td></td></tr>
<tr><td>_ROWID_</td>
......@@ -579,17 +601,17 @@ The following tokens are keywords in H2:
<tr><td>SELECT</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>SYSDATE</td>
<td>+</td><td></td><td></td><td></td><td></td><td></td></tr>
<td>CS</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>SYSTIME</td>
<td>+</td><td></td><td></td><td></td><td></td><td></td></tr>
<td>CS</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>SYSTIMESTAMP</td>
<td>+</td><td></td><td></td><td></td><td></td><td></td></tr>
<td>CS</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>TABLE</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>TODAY</td>
<td>+</td><td></td><td></td><td></td><td></td><td></td></tr>
<td>CS</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>TOP</td>
<td>+</td><td></td><td></td><td></td><td></td><td></td></tr>
<td>CS</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>TRUE</td>
<td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td></tr>
<tr><td>UNION</td>
......@@ -607,7 +629,9 @@ The following tokens are keywords in H2:
</tbody>
</table>
<p>
Most of them are also reserved (+) or non-reserved (NR) words in the SQL Standard.
Some keywords in H2 are context-sensitive (CS), such keywords may be used as identifiers in some places,
but cannot be used as identifiers in others.
Most keywords in H2 are also reserved (+) or non-reserved (NR) words in the SQL Standard.
Newer versions of H2 may have more keywords than older ones.
</p>
......
......@@ -718,9 +718,8 @@ public class Select extends Query {
}
}
int sampleSize = getSampleSizeValue(session);
LazyResultQueryFlat lazyResult = isForUpdateMvcc
? new LazyResultQueryFlatForUpdate(expressionArray, sampleSize, columnCount)
: new LazyResultQueryFlat(expressionArray, sampleSize, columnCount);
LazyResultQueryFlat lazyResult = new LazyResultQueryFlat(expressionArray, columnCount, sampleSize,
isForUpdateMvcc);
skipOffset(lazyResult, offset, quickOffset);
if (result == null) {
return lazyResult;
......@@ -1851,13 +1850,16 @@ public class Select extends Query {
/**
* Lazy execution for a flat query.
*/
private class LazyResultQueryFlat extends LazyResultSelect {
private final class LazyResultQueryFlat extends LazyResultSelect {
int sampleSize;
private int sampleSize;
LazyResultQueryFlat(Expression[] expressions, int sampleSize, int columnCount) {
private boolean forUpdate;
LazyResultQueryFlat(Expression[] expressions, int columnCount, int sampleSize, boolean forUpdate) {
super(expressions, columnCount);
this.sampleSize = sampleSize;
this.forUpdate = forUpdate;
}
@Override
......@@ -1865,7 +1867,7 @@ public class Select extends Query {
while ((sampleSize <= 0 || rowNumber < sampleSize) && topTableFilter.next()) {
setCurrentRowNumber(rowNumber + 1);
// This method may lock rows
if (isSelectConditionMet()) {
if (forUpdate ? isConditionMetForUpdate() : isConditionMet()) {
++rowNumber;
Value[] row = new Value[columnCount];
for (int i = 0; i < columnCount; i++) {
......@@ -1891,25 +1893,6 @@ public class Select extends Query {
return false;
}
boolean isSelectConditionMet() {
return isConditionMet();
}
}
/**
* Lazy execution for a flat for update query.
*/
private final class LazyResultQueryFlatForUpdate extends LazyResultQueryFlat {
LazyResultQueryFlatForUpdate(Expression[] expressions, int sampleSize, int columnCount) {
super(expressions, sampleSize, columnCount);
}
@Override
boolean isSelectConditionMet() {
return isConditionMetForUpdate();
}
}
/**
......
......@@ -1542,18 +1542,39 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* table/column/index name, in addition to the SQL-2003 keywords. The list
* returned is:
* <pre>
* INTERSECTS,LIMIT,MINUS,OFFSET,QUALIFY,ROWNUM,SYSDATE,SYSTIME,SYSTIMESTAMP,TODAY,TOP
* IF,ILIKE,INTERSECTS,
* LIMIT,
* MINUS,
* OFFSET,
* QUALIFY,
* REGEXP,_ROWID_,ROWNUM,
* SYSDATE,SYSTIME,SYSTIMESTAMP,
* TODAY,TOP
* </pre>
* The complete list of keywords (including SQL-2003 keywords) is:
* <pre>
* ALL, ARRAY, CASE, CHECK, CONSTRAINT, CROSS, CURRENT_DATE,
* CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, DISTINCT, EXCEPT,
* EXISTS, FALSE, FETCH, FOR, FOREIGN, FROM, FULL, GROUP, HAVING,
* IF, INNER, INTERSECT, INTERSECTS, INTERVAL, IS, JOIN, LIKE,
* LIMIT, LOCALTIME, LOCALTIMESTAMP, MINUS, NATURAL, NOT, NULL,
* OFFSET, ON, ORDER, PRIMARY, QUALIFY, ROW, _ROWID_, ROWNUM, SELECT,
* SYSDATE, SYSTIME, SYSTIMESTAMP, TABLE, TODAY, TOP, TRUE, UNION,
* UNIQUE, VALUES, WHERE, WINDOW, WITH
* ALL, AND, ARRAY, AS,
* BETWEEN,
* CASE, CHECK, CONSTRAINT, CROSS, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER,
* DISTINCT,
* EXCEPT, EXISTS,
* FALSE, FETCH, FILTER, FOR, FOREIGN, FROM, FULL,
* GROUP,
* HAVING,
* IF, ILIKE, IN, INNER, INTERSECT, INTERSECTS, INTERVAL, IS,
* JOIN,
* LEFT, LIKE, LIMIT, LOCALTIME, LOCALTIMESTAMP,
* MINUS,
* NATURAL, NOT, NULL,
* OFFSET, ON, OR, ORDER, OVER,
* PRIMARY,
* QUALIFY,
* REGEXP, RIGHT, ROW, _ROWID_, ROWNUM,
* SELECT, SYSDATE, SYSTIME, SYSTIMESTAMP,
* TABLE, TODAY, TOP, TRUE,
* UNION, UNIQUE,
* VALUES,
* WHERE, WINDOW, WITH
* </pre>
*
* @return a list of additional the keywords
......@@ -1561,7 +1582,14 @@ public class JdbcDatabaseMetaData extends TraceObject implements
@Override
public String getSQLKeywords() {
debugCodeCall("getSQLKeywords");
return "IF,INTERSECTS,LIMIT,MINUS,OFFSET,QUALIFY,_ROWID_,ROWNUM,SYSDATE,SYSTIME,SYSTIMESTAMP,TODAY,TOP";
return "IF,ILIKE,INTERSECTS," //
+ "LIMIT," //
+ "MINUS," //
+ "OFFSET," //
+ "QUALIFY," //
+ "REGEXP,_ROWID_,ROWNUM," //
+ "SYSDATE,SYSTIME,SYSTIMESTAMP," //
+ "TODAY,TOP";
}
/**
......
......@@ -362,11 +362,7 @@ public class MVPrimaryIndex extends BaseIndex {
* @return the maximum number of rows
*/
public long getRowCountMax() {
try {
return dataMap.sizeAsLongMax();
} catch (IllegalStateException e) {
throw DbException.get(ErrorCode.OBJECT_CLOSED, e);
}
return dataMap.sizeAsLongMax();
}
@Override
......
......@@ -367,6 +367,18 @@ public class ParserUtil {
} else if (eq("ARRAY", s, ignoreCase, start, end)) {
return ARRAY;
}
if (additionalKeywords) {
if (eq("AND", s, ignoreCase, start, end) || eq("AS", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'B':
if (additionalKeywords) {
if (eq("BETWEEN", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'C':
if (eq("CASE", s, ignoreCase, start, end)) {
......@@ -413,6 +425,11 @@ public class ParserUtil {
} else if (eq("FALSE", s, ignoreCase, start, end)) {
return FALSE;
}
if (additionalKeywords) {
if (eq("FILTER", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'G':
if (eq("GROUP", s, ignoreCase, start, end)) {
......@@ -438,6 +455,11 @@ public class ParserUtil {
} else if (eq("IS", s, ignoreCase, start, end)) {
return IS;
}
if (additionalKeywords) {
if (eq("ILIKE", s, ignoreCase, start, end) || eq("IN", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'J':
if (eq("JOIN", s, ignoreCase, start, end)) {
......@@ -454,6 +476,11 @@ public class ParserUtil {
} else if (eq("LOCALTIMESTAMP", s, ignoreCase, start, end)) {
return LOCALTIMESTAMP;
}
if (additionalKeywords) {
if (eq("LEFT", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'M':
if (eq("MINUS", s, ignoreCase, start, end)) {
......@@ -477,6 +504,11 @@ public class ParserUtil {
} else if (eq("ORDER", s, ignoreCase, start, end)) {
return ORDER;
}
if (additionalKeywords) {
if (eq("OR", s, ignoreCase, start, end) || eq("OVER", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'P':
if (eq("PRIMARY", s, ignoreCase, start, end)) {
......@@ -494,6 +526,11 @@ public class ParserUtil {
} else if (eq("ROWNUM", s, ignoreCase, start, end)) {
return ROWNUM;
}
if (additionalKeywords) {
if (eq("REGEXP", s, ignoreCase, start, end) || eq("RIGHT", s, ignoreCase, start, end)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'S':
if (eq("SELECT", s, ignoreCase, start, end)) {
......
......@@ -463,7 +463,14 @@ public class TestMetaData extends TestDb {
assertEquals("schema", meta.getSchemaTerm());
assertEquals("\\", meta.getSearchStringEscape());
assertEquals("IF,INTERSECTS,LIMIT,MINUS,OFFSET,QUALIFY,_ROWID_,ROWNUM,SYSDATE,SYSTIME,SYSTIMESTAMP,TODAY,TOP",
assertEquals("IF,ILIKE,INTERSECTS," //
+ "LIMIT," //
+ "MINUS," //
+ "OFFSET," //
+ "QUALIFY," //
+ "REGEXP,_ROWID_,ROWNUM," //
+ "SYSDATE,SYSTIME,SYSTIMESTAMP," //
+ "TODAY,TOP", //
meta.getSQLKeywords());
assertTrue(meta.getURL().startsWith("jdbc:h2:"));
......
......@@ -87,6 +87,12 @@ public class TestKeywords extends TestBase {
assertEquals(10, rs.getInt(1));
assertFalse(rs.next());
}
try (ResultSet rs = stat.executeQuery("SELECT SUM(" + s + ") " + s + " FROM " + s + ' ' + s)) {
assertTrue(rs.next());
assertEquals(10, rs.getInt(1));
assertFalse(rs.next());
assertEquals(s, rs.getMetaData().getColumnLabel(1));
}
} catch (Throwable t) {
throw new AssertionError(s + " cannot be used as identifier.", t);
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论