提交 d98ad361 authored 作者: Thomas Mueller's avatar Thomas Mueller

VALUES is now supported as a standalone command and as a table source: SELECT *…

VALUES is now supported as a standalone command and as a table source: SELECT * FROM (VALUES(1, 'Hello'), (2, 'World')) AS V;
上级 ff7bcccc
...@@ -1916,7 +1916,7 @@ ID + 20 ...@@ -1916,7 +1916,7 @@ ID + 20
" "
"Other Grammar","Table Expression"," "Other Grammar","Table Expression","
{ [ schemaName. ] tableName | ( select ) } [ [ AS ] newTableAlias ] { [ schemaName. ] tableName | ( select ) | valuesExpression } [ [ AS ] newTableAlias ]
[ { { LEFT | RIGHT } [ OUTER ] | [ INNER ] | CROSS | NATURAL } [ { { LEFT | RIGHT } [ OUTER ] | [ INNER ] | CROSS | NATURAL }
JOIN tableExpression [ ON expression ] ] JOIN tableExpression [ ON expression ] ]
"," ","
...@@ -1927,6 +1927,15 @@ columns with the same name. ...@@ -1927,6 +1927,15 @@ columns with the same name.
TEST AS T LEFT JOIN TEST AS T1 ON T.ID = T1.ID TEST AS T LEFT JOIN TEST AS T1 ON T.ID = T1.ID
" "
"Other Grammar","Values Expression","
VALUES { ( expression [,...] ) } [,...]
","
A list of rows that can be used like a table.
The column list of the resulting table is C1, C2, and so on.
","
SELECT * FROM (VALUES(1, 'Hello'), (2, 'World')) AS V;
"
"Other Grammar","Term"," "Other Grammar","Term","
value value
| columnName | columnName
...@@ -3122,7 +3131,7 @@ CURRENT_TIMESTAMP() ...@@ -3122,7 +3131,7 @@ CURRENT_TIMESTAMP()
" "
"Functions (Time and Date)","DATEADD"," "Functions (Time and Date)","DATEADD","
DATEADD(unitString, addInt, timestamp) { DATEADD| TIMESTAMPADD } (unitString, addInt, timestamp)
"," ","
Adds units to a timestamp. The string indicates the unit. Adds units to a timestamp. The string indicates the unit.
Use negative values to subtract units. Use negative values to subtract units.
...@@ -3139,7 +3148,6 @@ Returns the the number of crossed unit boundaries between two timestamps. ...@@ -3139,7 +3148,6 @@ Returns the the number of crossed unit boundaries between two timestamps.
This method returns a long. This method returns a long.
The string indicates the unit. The string indicates the unit.
The same units as in the EXTRACT function are supported. The same units as in the EXTRACT function are supported.
TIMESTAMPDIFF is supported for MySQL compatibility.
"," ","
DATEDIFF('YEAR', T1.CREATED, T2.CREATED) DATEDIFF('YEAR', T1.CREATED, T2.CREATED)
" "
......
...@@ -426,7 +426,7 @@ public class Parser { ...@@ -426,7 +426,7 @@ public class Parser {
case 'v': case 'v':
case 'V': case 'V':
if (readIf("VALUES")) { if (readIf("VALUES")) {
c = parseCall(); c = parseValues();
} }
break; break;
case 'w': case 'w':
...@@ -1037,6 +1037,8 @@ public class Parser { ...@@ -1037,6 +1037,8 @@ public class Parser {
} }
return top; return top;
} }
} else if (readIf("VALUES")) {
table = parseValuesTable().getTable();
} else { } else {
String tableName = readIdentifierWithSchema(null); String tableName = readIdentifierWithSchema(null);
Schema schema = getSchema(); Schema schema = getSchema();
...@@ -2169,6 +2171,7 @@ public class Parser { ...@@ -2169,6 +2171,7 @@ public class Parser {
read(")"); read(")");
break; break;
} }
case Function.DATE_ADD:
case Function.DATE_DIFF: { case Function.DATE_DIFF: {
if (Function.isDatePart(currentToken)) { if (Function.isDatePart(currentToken)) {
function.setParameter(0, ValueExpression.get(ValueString.get(currentToken))); function.setParameter(0, ValueExpression.get(ValueString.get(currentToken)));
...@@ -3874,6 +3877,91 @@ public class Parser { ...@@ -3874,6 +3877,91 @@ public class Parser {
return command; return command;
} }
private Select parseValues() {
Select command = new Select(session);
currentSelect = command;
TableFilter filter = parseValuesTable();
ArrayList<Expression> list = New.arrayList();
list.add(new Wildcard(null, null));
command.setExpressions(list);
command.addTableFilter(filter, true);
command.init();
return command;
}
private TableFilter parseValuesTable() {
Schema mainSchema = database.getSchema(Constants.SCHEMA_MAIN);
TableFunction tf = (TableFunction) Function.getFunction(database, "TABLE");
ArrayList<Column> columns = New.arrayList();
ArrayList<ArrayList<Expression>> rows = New.arrayList();
do {
int i = 0;
ArrayList<Expression> row = New.arrayList();
boolean multiColumn = readIf("(");
do {
Expression expr = readExpression();
expr = expr.optimize(session);
int type = expr.getType();
long prec;
int scale, displaySize;
Column column;
String columnName = "C" + (i + 1);
if (rows.size() == 0) {
if (type == Value.UNKNOWN) {
type = Value.STRING;
}
DataType dt = DataType.getDataType(type);
prec = dt.defaultPrecision;
scale = dt.defaultScale;
displaySize = dt.defaultDisplaySize;
column = new Column(columnName, type, prec, scale, displaySize);
columns.add(column);
}
prec = expr.getPrecision();
scale = expr.getScale();
displaySize = expr.getDisplaySize();
Column c = columns.get(i);
type = Value.getHigherOrder(c.getType(), type);
prec = Math.max(c.getPrecision(), prec);
scale = Math.max(c.getScale(), scale);
displaySize = Math.max(c.getDisplaySize(), displaySize);
column = new Column(columnName, type, prec, scale, displaySize);
columns.set(i, column);
row.add(expr);
i++;
} while (multiColumn && readIf(","));
if (multiColumn) {
read(")");
}
rows.add(row);
} while (readIf(","));
int columnCount = columns.size();
int rowCount = rows.size();
for (int i = 0; i < rowCount; i++) {
if (rows.get(i).size() != columnCount) {
throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH, "row " + (i + 1));
}
}
for (int i = 0; i < columnCount; i++) {
Column c = columns.get(i);
if (c.getType() == Value.UNKNOWN) {
c = new Column(c.getName(), Value.STRING, 0, 0, 0);
columns.set(i, c);
}
Expression[] array = new Expression[rowCount];
for (int j = 0; j < rowCount; j++) {
array[j] = rows.get(j).get(i);
}
ExpressionList list = new ExpressionList(array);
tf.setParameter(i, list);
}
tf.setColumns(columns);
tf.doneWithParameters();
Table table = new FunctionTable(mainSchema, session, tf, tf);
TableFilter filter = new TableFilter(session, table, null, rightsChecked, currentSelect);
return filter;
}
private Call parseCall() { private Call parseCall() {
Call command = new Call(session); Call command = new Call(session);
currentPrepared = command; currentPrepared = command;
......
...@@ -44,6 +44,7 @@ public class TestPreparedStatement extends TestBase { ...@@ -44,6 +44,7 @@ public class TestPreparedStatement extends TestBase {
public void test() throws Exception { public void test() throws Exception {
deleteDb("preparedStatement"); deleteDb("preparedStatement");
Connection conn = getConnection("preparedStatement"); Connection conn = getConnection("preparedStatement");
testValues(conn);
testToString(conn); testToString(conn);
testExecuteUpdateCall(conn); testExecuteUpdateCall(conn);
testPrepareExecute(conn); testPrepareExecute(conn);
...@@ -79,6 +80,34 @@ public class TestPreparedStatement extends TestBase { ...@@ -79,6 +80,34 @@ public class TestPreparedStatement extends TestBase {
deleteDb("preparedStatement"); deleteDb("preparedStatement");
} }
private void testValues(Connection conn) throws SQLException {
PreparedStatement prep = conn.prepareStatement("values(?, ?)");
prep.setInt(1, 1);
prep.setString(2, "Hello");
ResultSet rs = prep.executeQuery();
rs.next();
assertEquals(1, rs.getInt(1));
assertEquals("Hello", rs.getString(2));
prep = conn.prepareStatement("select * from values(?, ?), (2, 'World!')");
prep.setInt(1, 1);
prep.setString(2, "Hello");
rs = prep.executeQuery();
rs.next();
assertEquals(1, rs.getInt(1));
assertEquals("Hello", rs.getString(2));
rs.next();
assertEquals(2, rs.getInt(1));
assertEquals("World!", rs.getString(2));
prep = conn.prepareStatement("values 1, 2");
rs = prep.executeQuery();
rs.next();
assertEquals(1, rs.getInt(1));
rs.next();
assertEquals(2, rs.getInt(1));
}
private void testToString(Connection conn) throws SQLException { private void testToString(Connection conn) throws SQLException {
PreparedStatement prep = conn.prepareStatement("call 1"); PreparedStatement prep = conn.prepareStatement("call 1");
assertTrue(prep.toString().endsWith(": call 1")); assertTrue(prep.toString().endsWith(": call 1"));
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论