提交 31fac352 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Parse table value constructor in more places

上级 ea64e353
......@@ -21,6 +21,10 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Issue #1677: Unable to use VALUES keyword in WHERE clause
</li>
<li>Issue #1672: Deadlock on MVStore close in TestOutOfMemory
</li>
<li>Issue #1665: TestCrashAPI: NPE with ENUM in MINUS operator
</li>
<li>Issue #1602: Combine type, precision, scale, display size and extTypeInfo into one object
......
......@@ -415,11 +415,13 @@ To keep the content of an in-memory database as long as the virtual machine is a
<p>
The database files can be encrypted.
Three encryption algorithms are supported:
</p>
<ul>
<li>"AES" - also known as Rijndael, only AES-128 is implemented.</li>
<li>"XTEA" - the 32 round version.</li>
<li>"FOG" - pseudo-encryption only useful for hiding data from a text editor.</li>
</ul>
<p>
To use file encryption, you need to specify the encryption algorithm (the 'cipher')
and the file password (in addition to the user password) when connecting to the database.
</p>
......@@ -906,8 +908,10 @@ or the SQL statement <code>SET MODE MySQL</code>. Use this mode for compatibilit
digits are not truncated, but the value is rounded.
</li><li>Concatenating <code>NULL</code> with another value
results in the other value.
</li><li>ON DUPLICATE KEY UPDATE is supported in INSERT statements.
</li><li>INSERT IGNORE is partially supported and may be used to skip rows with duplicate keys if ON DUPLICATE KEY UPDATE is not specified.
</li><li>ON DUPLICATE KEY UPDATE is supported in INSERT statements, due to this feature VALUES has special non-standard
meaning is some contexts.
</li><li>INSERT IGNORE is partially supported and may be used to skip rows with duplicate keys if ON DUPLICATE KEY
UPDATE is not specified.
</li><li>REGEXP_REPLACE() uses \ for back-references for compatibility with MariaDB.
</li><li>Datetime value functions return the same value within a command.
</li></ul>
......@@ -1467,6 +1471,7 @@ For some examples, have a look at the code in <code>org.h2.test.db.TestTableEngi
<p>
In order to create your own TableEngine, you need to implement the <code>org.h2.api.TableEngine</code> interface e.g.
something like this:
</p>
<pre>
package acme;
public static class MyTableEngine implements org.h2.api.TableEngine {
......@@ -1480,12 +1485,13 @@ public static class MyTableEngine implements org.h2.api.TableEngine {
}
}
</pre>
<p>
and then create the table from SQL like this:
</p>
<pre>
CREATE TABLE TEST(ID INT, NAME VARCHAR)
ENGINE "acme.MyTableEngine";
</pre>
</p>
<p>
It is also possible to pass in parameters to the table engine, like so:
</p>
......
......@@ -253,7 +253,8 @@ import org.h2.value.ValueTimestampTimeZone;
public class Parser {
private static final String WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS =
"WITH statement supports only SELECT, TABLE, CREATE TABLE, INSERT, UPDATE, MERGE or DELETE statements";
"WITH statement supports only SELECT, TABLE, VALUES, " +
"CREATE TABLE, INSERT, UPDATE, MERGE or DELETE statements";
// used during the tokenizer phase
private static final int CHAR_END = 1, CHAR_VALUE = 2, CHAR_QUOTED = 3;
......@@ -755,11 +756,8 @@ public class Parser {
case FROM:
case SELECT:
case TABLE:
c = parseSelect();
break;
case VALUES:
read();
c = parseValues();
c = parseSelect();
break;
case WITH:
read();
......@@ -1450,6 +1448,7 @@ public class Parser {
switch (currentTokenType) {
case FROM:
case SELECT:
case VALUES:
case WITH:
select = true;
break;
......@@ -2350,6 +2349,7 @@ public class Parser {
case FROM:
case SELECT:
case TABLE:
case VALUES:
case WITH:
case OPEN_PAREN:
Query query = parseSelect();
......@@ -2696,6 +2696,8 @@ public class Parser {
command.setExpressions(expressions);
setSQL(command, "TABLE", start);
return command;
} else if (readIf(VALUES)) {
return parseValues();
} else {
throw getSyntaxError();
}
......@@ -3936,8 +3938,12 @@ public class Parser {
read();
break;
case VALUES:
read();
r = readKeywordFunction("VALUES");
if (database.getMode().onDuplicateKeyUpdate) {
read();
r = readKeywordFunction("VALUES");
} else {
r = new Subquery(parseSelect());
}
break;
case CASE:
read();
......@@ -5823,14 +5829,12 @@ public class Parser {
TableFilter filter = parseValuesTable(0);
command.setWildcard();
command.addTableFilter(filter, true);
command.init();
return command;
}
private TableFilter parseValuesTable(int orderInFrom) {
Schema mainSchema = database.getSchema(Constants.SCHEMA_MAIN);
TableFunction tf = (TableFunction) Function.getFunction(database,
"TABLE");
TableFunction tf = (TableFunction) Function.getFunction(database, "TABLE");
ArrayList<Column> columns = Utils.newSmallArrayList();
ArrayList<ArrayList<Expression>> rows = Utils.newSmallArrayList();
do {
......@@ -5885,9 +5889,7 @@ public class Parser {
tf.setColumns(columns);
tf.doneWithParameters();
Table table = new FunctionTable(mainSchema, session, tf, tf);
return new TableFilter(session, table, null,
rightsChecked, currentSelect, orderInFrom,
null);
return new TableFilter(session, table, null, rightsChecked, currentSelect, orderInFrom, null);
}
private Call parseCall() {
......@@ -6163,7 +6165,7 @@ public class Parser {
while (readIf(OPEN_PAREN)) {
parentheses++;
}
if (isToken(SELECT)) {
if (isToken(SELECT) || isToken(VALUES)) {
p = parseWithQuery();
} else if (isToken(TABLE)) {
int index = lastParseIndex;
......
......@@ -509,3 +509,31 @@ SELECT RAND() A, RAND() + 1 B, RAND() + 1 C, RAND() D, RAND() + 2 E, RAND() + 3
> rows: 1
@reconnect on
CREATE TABLE TEST (A INT, B INT, C INT);
> ok
INSERT INTO TEST VALUES (11, 12, 13), (21, 22, 23), (31, 32, 33);
> update count: 3
SELECT * FROM TEST WHERE (A, B) IN (VALUES (11, 12), (21, 22), (41, 42));
> A B C
> -- -- --
> 11 12 13
> 21 22 23
> rows: 2
SELECT * FROM TEST WHERE (A, B) = (VALUES (11, 12));
> A B C
> -- -- --
> 11 12 13
> rows: 1
DROP TABLE TEST;
> ok
VALUES (1, 2);
> C1 C2
> -- --
> 1 2
> rows: 1
......@@ -146,6 +146,12 @@ WITH CTE_TEST AS (TABLE TEST) ((TABLE CTE_TEST));
> 1 2
> rows: 1
WITH CTE_TEST AS (VALUES (1, 2)) ((SELECT * FROM CTE_TEST));
> C1 C2
> -- --
> 1 2
> rows: 1
WITH CTE_TEST AS (TABLE TEST) ((SELECT A, B FROM CTE_TEST2));
> exception TABLE_OR_VIEW_NOT_FOUND_1
......
......@@ -806,4 +806,4 @@ econd irst bcef ordinality nord unnest
analyst occupation distributive josaph aor engineer sajeewa isuru randil kevin doctor businessman artist ashan
corrupts splitted disruption unintentional octets preconditions predicates subq objectweb insn opcodes
preserves masking holder unboxing avert iae transformed subtle reevaluate exclusions subclause ftbl rgr
presorted inclusion
presorted inclusion contexts
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论