From 49484fecbb959f1c94814a8dd040f49c673fbef2 Mon Sep 17 00:00:00 2001 From: Hyunsik Choi Date: Mon, 19 Oct 2015 23:20:56 -0700 Subject: [PATCH 1/2] TAJO-1653: Add 'INSERT INTO VALUES' statement for OLTP-like storages. --- .../tajo/engine/query/TestInsertQuery.java | 40 ++++++++--- .../TestSQLAnalyzer/insert_values_1.sql | 1 + .../TestSQLAnalyzer/insert_values_1.result | 72 +++++++++++++++++++ .../tajo/master/exec/QueryExecutor.java | 2 +- .../apache/tajo/parser/sql/SQLAnalyzer.java | 12 +++- .../org/apache/tajo/parser/sql/SQLParser.g4 | 12 ++-- 6 files changed, 124 insertions(+), 15 deletions(-) create mode 100644 tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/insert_values_1.sql create mode 100644 tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/insert_values_1.result diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java index d0088a52cf..790eb32565 100644 --- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java +++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java @@ -37,6 +37,7 @@ import java.io.InputStreamReader; import java.sql.ResultSet; import java.util.List; +import java.util.UUID; import static org.junit.Assert.*; @@ -627,16 +628,14 @@ public final void testInsertOverwriteWithDatabase() throws Exception { executeString("DROP TABLE table1 PURGE"); } - @Test - public final void testInsertOverwriteTableWithNonFromQuery() throws Exception { - String tableName = CatalogUtil.normalizeIdentifier("InsertOverwriteWithEvalQuery"); + public final void testInsertOverwriteAllValues(String rawTableName, String query) throws Exception { + String tableName = CatalogUtil.normalizeIdentifier(rawTableName); ResultSet res = executeString("create table " + tableName +" (col1 int4, col2 float4, col3 text)"); res.close(); CatalogService catalog = testingCluster.getMaster().getCatalog(); assertTrue(catalog.existsTable(getCurrentDatabase(), tableName)); - res = executeString("insert overwrite into " + tableName - + " select 1::INT4, 2.1::FLOAT4, 'test'; "); + res = executeString(query); res.close(); @@ -658,13 +657,24 @@ public final void testInsertOverwriteTableWithNonFromQuery() throws Exception { } @Test - public final void testInsertOverwriteTableWithNonFromQuery2() throws Exception { - String tableName = CatalogUtil.normalizeIdentifier("InsertOverwriteWithEvalQuery2"); + public final void testInsertOverwriteAllValues1() throws Exception { + String tbName = getMethodName(); + testInsertOverwriteAllValues(tbName, "insert overwrite into " + tbName + " select 1::INT4, 2.1::FLOAT4, 'test'; "); + } + + @Test + public final void testInsertOverwriteAllValues2() throws Exception { + String tbName = getMethodName(); + testInsertOverwriteAllValues(tbName, "insert overwrite into " + tbName + " VALUES(1::INT4, 2.1::FLOAT4, 'test');"); + } + + public final void testInsertOverwriteSomeValues(String rawTableName, String sql) throws Exception { + String tableName = CatalogUtil.normalizeIdentifier(rawTableName); ResultSet res = executeString("create table " + tableName +" (col1 int4, col2 float4, col3 text)"); res.close(); CatalogService catalog = testingCluster.getMaster().getCatalog(); assertTrue(catalog.existsTable(getCurrentDatabase(), tableName)); - res = executeString("insert overwrite into " + tableName + " (col1, col3) select 1::INT4, 'test';"); + res = executeString(sql); res.close(); TableDesc desc = catalog.getTableDesc(getCurrentDatabase(), tableName); @@ -685,6 +695,20 @@ public final void testInsertOverwriteTableWithNonFromQuery2() throws Exception { executeString("DROP TABLE " + tableName + " PURGE"); } + @Test + public final void testInsertOverwriteTableSomeValues1() throws Exception { + String tbName = getMethodName(); + testInsertOverwriteSomeValues(tbName, + "insert overwrite into " + tbName + " (col1, col3) select 1::INT4, 'test'"); + } + + @Test + public final void testInsertOverwriteTableSomeValues2() throws Exception { + String tbName = getMethodName(); + testInsertOverwriteSomeValues(tbName, + "insert overwrite into " + tbName + " (col1, col3) VALUES(1::INT4, 'test')"); + } + @Test public final void testInsertOverwritePathWithNonFromQuery() throws Exception { ResultSet res = executeString("insert overwrite into location " + diff --git a/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/insert_values_1.sql b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/insert_values_1.sql new file mode 100644 index 0000000000..5fe137de49 --- /dev/null +++ b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/insert_values_1.sql @@ -0,0 +1 @@ +INSERT INTO table1 VALUES (1, 2.3, "str", date '1980-04-01', time '01:50:00', timestamp '1980-04-1 01:50:00'); diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/insert_values_1.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/insert_values_1.result new file mode 100644 index 0000000000..70249a76b3 --- /dev/null +++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/insert_values_1.result @@ -0,0 +1,72 @@ +{ + "IsOverwrite": false, + "TableName": "table1", + "SubPlan": { + "IsDistinct": false, + "Projections": [ + { + "Expr": { + "Value": "1", + "ValueType": "Unsigned_Integer", + "OpType": "Literal" + }, + "OpType": "Target" + }, + { + "Expr": { + "Value": "2.3", + "ValueType": "Unsigned_Float", + "OpType": "Literal" + }, + "OpType": "Target" + }, + { + "Expr": { + "ColumnName": "str", + "OpType": "Column" + }, + "OpType": "Target" + }, + { + "Expr": { + "Date": { + "Year": "1980", + "Month": "04", + "Day": "01" + }, + "OpType": "DateLiteral" + }, + "OpType": "Target" + }, + { + "Expr": { + "Time": { + "Hour": "01", + "Minute": "50", + "Second": "00" + }, + "OpType": "TimeLiteral" + }, + "OpType": "Target" + }, + { + "Expr": { + "Date": { + "Year": "1980", + "Month": "04", + "Day": "1" + }, + "Time": { + "Hour": "01", + "Minute": "50", + "Second": "00" + }, + "OpType": "TimestampLiteral" + }, + "OpType": "Target" + } + ], + "OpType": "Projection" + }, + "OpType": "Insert" +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java b/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java index 83ceb3e12c..e260c003fd 100644 --- a/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java +++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java @@ -470,7 +470,7 @@ private void insertRowValues(QueryContext queryContext, taskAttemptContext = new TaskAttemptContext(queryContext, null, null, null, null); taskAttemptContext.setOutputPath(new Path(finalOutputUri)); - EvalExprExec evalExprExec = new EvalExprExec(taskAttemptContext, (EvalExprNode) insertNode.getChild()); + EvalExprExec evalExprExec = new EvalExprExec(taskAttemptContext, insertNode.getChild()); InsertRowsExec exec = new InsertRowsExec(taskAttemptContext, insertNode, evalExprExec); try { diff --git a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java index 7b49d05212..2745a2ff6e 100644 --- a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java +++ b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java @@ -41,6 +41,7 @@ import org.apache.tajo.util.StringUtils; import java.util.*; +import java.util.stream.Collectors; import static org.apache.tajo.algebra.Aggregation.GroupElement; import static org.apache.tajo.algebra.CreateTable.*; @@ -1670,7 +1671,16 @@ public Expr visitInsert_statement(Insert_statementContext ctx) { } } - insertExpr.setSubQuery(visitQuery_expression(ctx.query_expression())); + if (checkIfExist(ctx.VALUES())) { + List values = ctx.row_value_predicand().stream() + .map(value -> new NamedExpr(visitRow_value_predicand(value))) + .collect(Collectors.toList()); + Projection projection = new Projection(); + projection.setNamedExprs(values.toArray(new NamedExpr[values.size()])); + insertExpr.setSubQuery(projection); + } else { + insertExpr.setSubQuery(visitQuery_expression(ctx.query_expression())); + } Preconditions.checkState(insertExpr.hasTableName() || insertExpr.hasLocation(), "Either a table name or a location should be given."); diff --git a/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4 b/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4 index e2693eae44..7bf2346789 100644 --- a/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4 +++ b/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4 @@ -951,7 +951,7 @@ parenthesized_boolean_value_expression /* =============================================================================== - 7.2 + 7.2 (p293) =============================================================================== */ row_value_expression @@ -959,10 +959,6 @@ row_value_expression | explicit_row_value_constructor ; -row_value_special_case - : nonparenthesized_value_expression_primary - ; - explicit_row_value_constructor : NULL ; @@ -978,6 +974,10 @@ row_value_constructor_predicand // | explicit_row_value_constructor ; +row_value_special_case + : nonparenthesized_value_expression_primary + ; + /* =============================================================================== 7.4 @@ -1605,6 +1605,8 @@ null_ordering insert_statement : INSERT (OVERWRITE)? INTO table_name (LEFT_PAREN column_reference_list RIGHT_PAREN)? query_expression + | INSERT (OVERWRITE)? INTO table_name (LEFT_PAREN column_reference_list RIGHT_PAREN)? VALUES + LEFT_PAREN row_value_predicand (COMMA row_value_predicand)* RIGHT_PAREN | INSERT (OVERWRITE)? INTO LOCATION path=Character_String_Literal (USING storage_type=identifier (param_clause)?)? query_expression ; From 532d5dd87b24e920ec8ea145d4b6a9c84fe87cde Mon Sep 17 00:00:00 2001 From: Hyunsik Choi Date: Mon, 19 Oct 2015 23:34:38 -0700 Subject: [PATCH 2/2] Removed unused imports. --- .../test/java/org/apache/tajo/engine/query/TestInsertQuery.java | 1 - 1 file changed, 1 deletion(-) diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java index 790eb32565..328eda544d 100644 --- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java +++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java @@ -37,7 +37,6 @@ import java.io.InputStreamReader; import java.sql.ResultSet; import java.util.List; -import java.util.UUID; import static org.junit.Assert.*;