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

Merge pull request #1255 from katzyn/misc

Minor changes in MERGE USING, DATE_TRUNC, and EXTRACT
......@@ -122,7 +122,7 @@ MERGE INTO TEST KEY(ID) VALUES(2, 'World')
"Commands (DML)","MERGE USING","
MERGE INTO targetTableName [ [AS] targetAlias]
USING { ( select ) | sourceTableName }[ [AS] sourceAlias ]
ON ( expression )
ON expression
[ WHEN MATCHED THEN
[ UPDATE SET setClauseList ] [ DELETE deleteSearchCondition ] ]
[ WHEN NOT MATCHED THEN INSERT insertColumnsAndSource ]
......@@ -138,20 +138,20 @@ If WHEN MATCHED THEN is specified it should contain UPDATE or DELETE clauses of
If statement doesn't need a source table a DUAL table can be substituted.
","
MERGE INTO TARGET_TABLE AS T USING SOURCE_TABLE AS S
ON (T.ID = S.ID)
ON T.ID = S.ID
WHEN MATCHED THEN
UPDATE SET T.COL1 = S.COL1 WHERE T.COL2<>'FINAL'
DELETE WHERE T.COL2='FINAL'
WHEN NOT MATCHED THEN
INSERT (ID,COL1,COL2) VALUES(S.ID,S.COL1,S.COL2)
MERGE INTO TARGET_TABLE AS T USING (SELECT * FROM SOURCE_TABLE) AS S
ON (T.ID = S.ID)
ON T.ID = S.ID
WHEN MATCHED THEN
UPDATE SET T.COL1 = S.COL1 WHERE T.COL2<>'FINAL'
DELETE WHERE T.COL2='FINAL'
WHEN NOT MATCHED THEN
INSERT (ID,COL1,COL2) VALUES(S.ID,S.COL1,S.COL2)
MERGE INTO TARGET_TABLE USING DUAL ON (ID = 1)
MERGE INTO TARGET_TABLE USING DUAL ON ID = 1
WHEN NOT MATCHED THEN INSERT (ID, NAME) VALUES (1, 'Test')
WHEN MATCHED THEN UPDATE SET NAME = 'Test'
"
......
......@@ -1170,10 +1170,8 @@ public class Parser {
command.setQuery(preparedQuery);
}
read("ON");
read("(");
Expression condition = readExpression();
command.setOnCondition(condition);
read(")");
read("WHEN");
boolean matched = readIf("MATCHED");
......
......@@ -2197,6 +2197,32 @@ public class Function extends Expression implements FunctionCall {
long p;
Expression p0 = args.length < 1 ? null : args[0];
switch (info.type) {
case EXTRACT: {
if (p0.isConstant() && DateTimeFunctions.getDatePart(p0.getValue(session).getString()) == Function.EPOCH) {
t = Value.DECIMAL;
p = ValueLong.PRECISION + ValueTimestamp.MAXIMUM_SCALE;
s = ValueTimestamp.MAXIMUM_SCALE;
d = ValueLong.PRECISION + ValueTimestamp.MAXIMUM_SCALE + 1;
} else {
t = Value.INT;
p = ValueInt.PRECISION;
s = 0;
d = ValueInt.DISPLAY_SIZE;
}
break;
}
case DATE_TRUNC: {
Expression p1 = args[1];
t = p1.getType();
if (t == Value.TIMESTAMP_TZ) {
p = d = ValueTimestampTimeZone.DEFAULT_PRECISION;
} else {
t = Value.TIMESTAMP;
p = d = ValueTimestamp.DEFAULT_PRECISION;
}
s = ValueTimestamp.MAXIMUM_SCALE;
break;
}
case IFNULL:
case NULLIF:
case COALESCE:
......
......@@ -576,7 +576,14 @@ public final class DateTimeFunctions {
}
}
private static int getDatePart(String part) {
/**
* Get date part function number from part name.
*
* @param part
* name of the part
* @return function number
*/
public static int getDatePart(String part) {
Integer p = DATE_PART.get(StringUtils.toUpperEnglish(part));
if (p == null) {
throw DbException.getInvalidValueException("date part", part);
......
......@@ -113,6 +113,8 @@ public class TestFunctions extends TestDb implements AggregateFunction {
testNvl2();
testConcatWs();
testTruncate();
testDateTrunc();
testExtract();
testToCharFromDateTime();
testToCharFromNumber();
testToCharFromText();
......@@ -1239,6 +1241,36 @@ public class TestFunctions extends TestDb implements AggregateFunction {
conn.close();
}
private void testDateTrunc() throws SQLException {
deleteDb("functions");
Connection conn = getConnection("functions");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(S VARCHAR, TS TIMESTAMP, D DATE, T TIME, TZ TIMESTAMP WITH TIME ZONE)");
stat.execute("INSERT INTO TEST VALUES ('2010-01-01 10:11:12', '2010-01-01 10:11:12', '2010-01-01', '10:11:12', '2010-01-01 10:11:12Z')");
ResultSetMetaData md = stat.executeQuery("SELECT DATE_TRUNC('HOUR', S), DATE_TRUNC('HOUR', TS),"
+ " DATE_TRUNC('HOUR', D), DATE_TRUNC('HOUR', T), DATE_TRUNC('HOUR', TZ) FROM TEST")
.getMetaData();
assertEquals(Types.TIMESTAMP, md.getColumnType(1));
assertEquals(Types.TIMESTAMP, md.getColumnType(2));
assertEquals(Types.TIMESTAMP, md.getColumnType(3));
assertEquals(Types.TIMESTAMP, md.getColumnType(4));
assertEquals(/* TODO use Types.TIMESTAMP_WITH_TIMEZONE on Java 8 */ 2014, md.getColumnType(5));
conn.close();
}
private void testExtract() throws SQLException {
deleteDb("functions");
Connection conn = getConnection("functions");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(TS TIMESTAMP)");
stat.execute("INSERT INTO TEST VALUES ('2010-01-01 10:11:12')");
assertEquals(Types.INTEGER, stat.executeQuery("SELECT EXTRACT(DAY FROM TS) FROM TEST")
.getMetaData().getColumnType(1));
assertEquals(Types.DECIMAL, stat.executeQuery("SELECT EXTRACT(EPOCH FROM TS) FROM TEST")
.getMetaData().getColumnType(1));
conn.close();
}
private void testTranslate() throws SQLException {
Connection conn = getConnection("functions");
Statement stat = conn.createStatement();
......
......@@ -166,7 +166,7 @@ public class TestMergeUsing extends TestDb implements Trigger {
GATHER_ORDERED_RESULTS_SQL,
"SELECT X AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(1,3) WHERE X<0",
0,
"expected \"WHEN\"");
"WHEN\"");
// Two updates to same row - update and delete together - emptying the
// parent table
testMergeUsing(
......
......@@ -118,7 +118,7 @@ DROP TABLE DEST_TABLE;
CREATE TABLE TEST(C1 INT, C2 INT, C3 INT);
> ok
MERGE INTO TEST USING DUAL ON (C1 = 11 AND C2 = 21)
MERGE INTO TEST USING DUAL ON C1 = 11 AND C2 = 21
WHEN NOT MATCHED THEN INSERT (C1, C2, C3) VALUES (11, 21, 31)
WHEN MATCHED THEN UPDATE SET C3 = 31;
> update count: 1
......@@ -135,7 +135,7 @@ SELECT * FROM TEST ORDER BY C1, C2;
> 11 22 32
> rows (ordered): 2
MERGE INTO TEST USING DUAL ON (C1 = 11 AND C2 = 21)
MERGE INTO TEST USING DUAL ON C1 = 11 AND C2 = 21
WHEN NOT MATCHED THEN INSERT (C1, C2, C3) VALUES (11, 21, 33)
WHEN MATCHED THEN UPDATE SET C3 = 33;
> update count: 1
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论