提交 cc12be67 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Parse row values with ROW() and with unparenthesed syntax in more places

上级 31fac352
......@@ -129,6 +129,7 @@ import org.h2.command.ddl.TruncateTable;
import org.h2.command.dml.AlterTableSet;
import org.h2.command.dml.BackupCommand;
import org.h2.command.dml.Call;
import org.h2.command.dml.CommandWithValues;
import org.h2.command.dml.Delete;
import org.h2.command.dml.ExecuteProcedure;
import org.h2.command.dml.Explain;
......@@ -1491,10 +1492,7 @@ public class Parser {
command.setKeys(keys);
}
if (readIf(VALUES)) {
do {
read(OPEN_PAREN);
command.addRow(parseValuesForInsert());
} while (readIf(COMMA));
parseValuesForCommand(command);
} else {
command.setQuery(parseSelect());
}
......@@ -1681,11 +1679,7 @@ public class Parser {
Expression[] expr = {};
command.addRow(expr);
} else if (readIf(VALUES)) {
read(OPEN_PAREN);
do {
command.addRow(parseValuesForInsert());
// the following condition will allow (..),; and (..);
} while (readIf(COMMA) && readIf(OPEN_PAREN));
parseValuesForCommand(command);
} else if (readIf("SET")) {
if (columns != null) {
throw getSyntaxError();
......@@ -1724,28 +1718,35 @@ public class Parser {
command.setColumns(columns);
}
if (readIf(VALUES)) {
do {
read(OPEN_PAREN);
command.addRow(parseValuesForInsert());
} while (readIf(COMMA));
parseValuesForCommand(command);
} else {
command.setQuery(parseSelect());
}
return command;
}
private Expression[] parseValuesForInsert() {
private void parseValuesForCommand(CommandWithValues command) {
ArrayList<Expression> values = Utils.newSmallArrayList();
if (!readIf(CLOSE_PAREN)) {
do {
if (readIf("DEFAULT")) {
values.add(null);
values.clear();
boolean multiColumn;
if (readIf(ROW)) {
read(OPEN_PAREN);
multiColumn = true;
} else {
values.add(readExpression());
multiColumn = readIf(OPEN_PAREN);
}
if (multiColumn) {
if (!readIf(CLOSE_PAREN)) {
do {
values.add(readIf("DEFAULT") ? null : readExpression());
} while (readIfMore(false));
}
return values.toArray(new Expression[0]);
} else {
values.add(readIf("DEFAULT") ? null : readExpression());
}
command.addRow(values.toArray(new Expression[0]));
} while (readIf(COMMA));
}
private TableFilter readTableFilter() {
......@@ -5840,7 +5841,13 @@ public class Parser {
do {
int i = 0;
ArrayList<Expression> row = Utils.newSmallArrayList();
boolean multiColumn = readIf(OPEN_PAREN);
boolean multiColumn;
if (readIf(ROW)) {
read(OPEN_PAREN);
multiColumn = true;
} else {
multiColumn = readIf(OPEN_PAREN);
}
do {
Expression expr = readExpression();
expr = expr.optimize(session);
......
/*
* Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.util.ArrayList;
import org.h2.command.Prepared;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.util.Utils;
/**
* Command that supports VALUES clause.
*/
public abstract class CommandWithValues extends Prepared {
protected final ArrayList<Expression[]> valuesExpressionList = Utils.newSmallArrayList();
/**
* Creates new instance of command with VALUES clause.
*
* @param session
* the session
*/
protected CommandWithValues(Session session) {
super(session);
}
/**
* Add a row to this command.
*
* @param expr
* the list of values
*/
public void addRow(Expression[] expr) {
valuesExpressionList.add(expr);
}
}
......@@ -12,7 +12,6 @@ import org.h2.api.ErrorCode;
import org.h2.api.Trigger;
import org.h2.command.Command;
import org.h2.command.CommandInterface;
import org.h2.command.Prepared;
import org.h2.engine.GeneratedKeys;
import org.h2.engine.Mode;
import org.h2.engine.Right;
......@@ -35,7 +34,6 @@ import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.util.StatementBuilder;
import org.h2.util.Utils;
import org.h2.value.Value;
import org.h2.value.ValueNull;
......@@ -43,11 +41,10 @@ import org.h2.value.ValueNull;
* This class represents the statement
* INSERT
*/
public class Insert extends Prepared implements ResultTarget {
public class Insert extends CommandWithValues implements ResultTarget {
private Table table;
private Column[] columns;
private final ArrayList<Expression[]> list = Utils.newSmallArrayList();
private Query query;
private boolean sortedInsertMode;
private int rowNumber;
......@@ -117,15 +114,6 @@ public class Insert extends Prepared implements ResultTarget {
duplicateKeyAssignmentMap.put(column, expression);
}
/**
* Add a row to this merge statement.
*
* @param expr the list of values
*/
public void addRow(Expression[] expr) {
list.add(expr);
}
@Override
public int update() {
Index index = null;
......@@ -157,14 +145,14 @@ public class Insert extends Prepared implements ResultTarget {
rowNumber = 0;
GeneratedKeys generatedKeys = session.getGeneratedKeys();
generatedKeys.initialize(table);
int listSize = list.size();
int listSize = valuesExpressionList.size();
if (listSize > 0) {
Mode mode = session.getDatabase().getMode();
int columnLen = columns.length;
for (int x = 0; x < listSize; x++) {
generatedKeys.nextRow();
Row newRow = table.getTemplateRow();
Expression[] expr = list.get(x);
Expression[] expr = valuesExpressionList.get(x);
setCurrentRowNumber(x + 1);
for (int i = 0; i < columnLen; i++) {
Column c = columns[i];
......@@ -294,13 +282,13 @@ public class Insert extends Prepared implements ResultTarget {
if (sortedInsertMode) {
buff.append("SORTED ");
}
if (!list.isEmpty()) {
if (!valuesExpressionList.isEmpty()) {
buff.append("VALUES ");
int row = 0;
if (list.size() > 1) {
if (valuesExpressionList.size() > 1) {
buff.append('\n');
}
for (Expression[] expr : list) {
for (Expression[] expr : valuesExpressionList) {
if (row++ > 0) {
buff.append(",\n");
}
......@@ -317,15 +305,15 @@ public class Insert extends Prepared implements ResultTarget {
@Override
public void prepare() {
if (columns == null) {
if (!list.isEmpty() && list.get(0).length == 0) {
if (!valuesExpressionList.isEmpty() && valuesExpressionList.get(0).length == 0) {
// special case where table is used as a sequence
columns = new Column[0];
} else {
columns = table.getColumns();
}
}
if (!list.isEmpty()) {
for (Expression[] expr : list) {
if (!valuesExpressionList.isEmpty()) {
for (Expression[] expr : valuesExpressionList) {
if (expr.length != columns.length) {
throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH);
}
......@@ -400,7 +388,7 @@ public class Insert extends Prepared implements ResultTarget {
ArrayList<String> variableNames = new ArrayList<>(
duplicateKeyAssignmentMap.size());
Expression[] row = (currentRow == null) ? list.get((int) getCurrentRowNumber() - 1)
Expression[] row = (currentRow == null) ? valuesExpressionList.get((int) getCurrentRowNumber() - 1)
: new Expression[columns.length];
for (int i = 0; i < columns.length; i++) {
String key = table.getSchema().getName() + "." +
......
......@@ -27,20 +27,18 @@ import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.util.StatementBuilder;
import org.h2.util.Utils;
import org.h2.value.Value;
/**
* This class represents the statement
* MERGE
*/
public class Merge extends Prepared {
public class Merge extends CommandWithValues {
private Table targetTable;
private TableFilter targetTableFilter;
private Column[] columns;
private Column[] keys;
private final ArrayList<Expression[]> valuesExpressionList = Utils.newSmallArrayList();
private Query query;
private Prepared update;
......@@ -72,15 +70,6 @@ public class Merge extends Prepared {
this.query = query;
}
/**
* Add a row to this merge statement.
*
* @param expr the list of values
*/
public void addRow(Expression[] expr) {
valuesExpressionList.add(expr);
}
@Override
public int update() {
int count;
......
......@@ -25,18 +25,16 @@ import org.h2.result.Row;
import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.util.StatementBuilder;
import org.h2.util.Utils;
import org.h2.value.Value;
/**
* This class represents the MySQL-compatibility REPLACE statement
*/
public class Replace extends Prepared {
public class Replace extends CommandWithValues {
private Table table;
private Column[] columns;
private Column[] keys;
private final ArrayList<Expression[]> list = Utils.newSmallArrayList();
private Query query;
private Prepared update;
......@@ -68,15 +66,6 @@ public class Replace extends Prepared {
this.query = query;
}
/**
* Add a row to this replace statement.
*
* @param expr the list of values
*/
public void addRow(Expression[] expr) {
list.add(expr);
}
@Override
public int update() {
int count = 0;
......@@ -84,10 +73,10 @@ public class Replace extends Prepared {
session.getUser().checkRight(table, Right.UPDATE);
setCurrentRowNumber(0);
Mode mode = session.getDatabase().getMode();
if (!list.isEmpty()) {
for (int x = 0, size = list.size(); x < size; x++) {
if (!valuesExpressionList.isEmpty()) {
for (int x = 0, size = valuesExpressionList.size(); x < size; x++) {
setCurrentRowNumber(x + 1);
Expression[] expr = list.get(x);
Expression[] expr = valuesExpressionList.get(x);
Row newRow = table.getTemplateRow();
for (int i = 0, len = columns.length; i < len; i++) {
Column c = columns[i];
......@@ -214,10 +203,10 @@ public class Replace extends Prepared {
}
buff.append(')');
buff.append('\n');
if (!list.isEmpty()) {
if (!valuesExpressionList.isEmpty()) {
buff.append("VALUES ");
int row = 0;
for (Expression[] expr : list) {
for (Expression[] expr : valuesExpressionList) {
if (row++ > 0) {
buff.append(", ");
}
......@@ -234,15 +223,15 @@ public class Replace extends Prepared {
@Override
public void prepare() {
if (columns == null) {
if (!list.isEmpty() && list.get(0).length == 0) {
if (!valuesExpressionList.isEmpty() && valuesExpressionList.get(0).length == 0) {
// special case where table is used as a sequence
columns = new Column[0];
} else {
columns = table.getColumns();
}
}
if (!list.isEmpty()) {
for (Expression[] expr : list) {
if (!valuesExpressionList.isEmpty()) {
for (Expression[] expr : valuesExpressionList) {
if (expr.length != columns.length) {
throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH);
}
......
......@@ -23,8 +23,7 @@ INSERT INTO VERSION VALUES
(134, '1.4.184', '2014-12-19'),
(133, '1.4.183', '2014-12-13'),
(132, '1.4.182', '2014-10-17'),
(131, '1.4.181', '2014-08-06'),
;
(131, '1.4.181', '2014-08-06');
CREATE TABLE CHANNEL(TITLE VARCHAR, LINK VARCHAR, DESC VARCHAR,
LANGUAGE VARCHAR, PUB TIMESTAMP, LAST TIMESTAMP, AUTHOR VARCHAR);
......
......@@ -154,8 +154,8 @@ public class TestScript extends TestDb {
"dropDomain", "dropIndex", "dropSchema", "truncateTable" }) {
testScript("ddl/" + s + ".sql");
}
for (String s : new String[] { "delete", "error_reporting", "insertIgnore", "merge", "mergeUsing", "replace",
"script", "select", "show", "table", "with" }) {
for (String s : new String[] { "delete", "error_reporting", "insert", "insertIgnore", "merge", "mergeUsing",
"replace", "script", "select", "show", "table", "with" }) {
testScript("dml/" + s + ".sql");
}
for (String s : new String[] { "help" }) {
......
-- Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
CREATE TABLE TEST(A INT, B INT);
> ok
INSERT INTO TEST VALUES ROW (1, 2), (3, 4), ROW (5, 6);
> update count: 3
INSERT INTO TEST(a) VALUES 7;
> update count: 1
INSERT INTO TEST(a) VALUES 8, 9;
> update count: 2
TABLE TEST;
> A B
> - ----
> 1 2
> 3 4
> 5 6
> 7 null
> 8 null
> 9 null
> rows: 6
DROP TABLE TEST;
> ok
......@@ -537,3 +537,16 @@ VALUES (1, 2);
> -- --
> 1 2
> rows: 1
VALUES ROW (1, 2);
> C1 C2
> -- --
> 1 2
> rows: 1
VALUES 1, 2;
> C1
> --
> 1
> 2
> rows: 2
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论