| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * <p> |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * <p> |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.odpi.specs.runtime.hive; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.junit.Test; |
| |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| |
| // This does not test every option that Hive supports, but does try to touch the major |
| // options, especially anything unique to Hive. See each test for areas tested and not tested. |
| public class TestSql extends JdbcConnector { |
| private static final Log LOG = LogFactory.getLog(TestSql.class.getName()); |
| |
| @Test |
| public void db() throws SQLException { |
| final String db1 = "odpi_sql_db1"; |
| final String db2 = "odpi_sql_db2"; |
| try (Statement stmt = conn.createStatement()) { |
| stmt.execute("drop database if exists " + db1 + " cascade"); |
| |
| // Simple create database |
| stmt.execute("create database " + db1); |
| stmt.execute("drop database " + db1); |
| |
| stmt.execute("drop schema if exists " + db2 + " cascade"); |
| |
| String location = getProperty(LOCATION, "a writable directory in HDFS"); |
| |
| // All the bells and whistles |
| stmt.execute("create schema if not exists " + db2 + " comment 'a db' location '" + location + |
| "' with dbproperties ('a' = 'b')"); |
| |
| stmt.execute("alter database " + db2 + " set dbproperties ('c' = 'd')"); |
| |
| stmt.execute("drop database " + db2 + " restrict"); |
| } |
| } |
| |
| @Test |
| public void table() throws SQLException { |
| final String table1 = "odpi_sql_table1"; |
| final String table2 = "odpi_sql_table2"; |
| final String table3 = "odpi_sql_table3"; |
| final String table4 = "odpi_sql_table4"; |
| final String table5 = "odpi_sql_table5"; |
| |
| try (Statement stmt = conn.createStatement()) { |
| stmt.execute("drop table if exists " + table1); |
| stmt.execute("drop table if exists " + table2); |
| stmt.execute("drop table if exists " + table3); |
| stmt.execute("drop table if exists " + table4); |
| stmt.execute("drop table if exists " + table5); |
| |
| String location = getProperty(LOCATION, "a writable directory in HDFS"); |
| stmt.execute("create external table " + table1 + "(a int, b varchar(32)) location '" + |
| location + "'"); |
| |
| // With a little bit of everything, except partitions, we'll do those below |
| stmt.execute("create table if not exists " + table2 + |
| "(c1 tinyint," + |
| " c2 smallint," + |
| " c3 int comment 'a column comment'," + |
| " c4 bigint," + |
| " c5 float," + |
| " c6 double," + |
| " c7 decimal," + |
| " c8 decimal(12)," + |
| " c9 decimal(8,2)," + |
| " c10 timestamp," + |
| " c11 date," + |
| " c12 string," + |
| " c13 varchar(120)," + |
| " c14 char(10)," + |
| " c15 boolean," + |
| " c16 binary," + |
| " c17 array<string>," + |
| " c18 map <string, string>," + |
| " c19 struct<s1:int, s2:bigint>," + |
| " c20 uniontype<int, string>) " + |
| "comment 'table comment'" + |
| "clustered by (c1) sorted by (c2) into 10 buckets " + |
| "stored as orc " + |
| "tblproperties ('a' = 'b')"); |
| |
| // Not testing SKEWED BY, ROW FORMAT, STORED BY (storage handler |
| |
| stmt.execute("create temporary table " + table3 + " like " + table2); |
| |
| stmt.execute("insert into " + table1 + " values (3, 'abc'), (4, 'def')"); |
| |
| stmt.execute("create table " + table4 + " as select a, b from " + table1); |
| |
| stmt.execute("truncate table " + table4); |
| |
| stmt.execute("alter table " + table4 + " rename to " + table5); |
| stmt.execute("alter table " + table2 + " set tblproperties ('c' = 'd')"); |
| |
| // Not testing alter of clustered or sorted by, because that's suicidal |
| // Not testing alter of skewed or serde properties since we didn't test it for create |
| // above. |
| |
| stmt.execute("drop table " + table1 + " purge"); |
| stmt.execute("drop table " + table2); |
| stmt.execute("drop table " + table3); |
| stmt.execute("drop table " + table5); |
| } |
| } |
| |
| @Test |
| public void partitionedTable() throws SQLException { |
| final String table1 = "odpi_sql_ptable1"; |
| try (Statement stmt = conn.createStatement()) { |
| stmt.execute("drop table if exists " + table1); |
| |
| stmt.execute("create table " + table1 + |
| "(c1 int," + |
| " c2 varchar(32))" + |
| "partitioned by (p1 string comment 'a partition column')" + |
| "stored as orc"); |
| |
| stmt.execute("alter table " + table1 + " add partition (p1 = 'a')"); |
| stmt.execute("insert into " + table1 + " partition (p1 = 'a') values (1, 'abc')"); |
| stmt.execute("insert into " + table1 + " partition (p1 = 'a') values (2, 'def')"); |
| stmt.execute("insert into " + table1 + " partition (p1 = 'a') values (3, 'ghi')"); |
| stmt.execute("alter table " + table1 + " partition (p1 = 'a') concatenate"); |
| stmt.execute("alter table " + table1 + " touch partition (p1 = 'a')"); |
| |
| stmt.execute("alter table " + table1 + " add columns (c3 float)"); |
| stmt.execute("alter table " + table1 + " drop partition (p1 = 'a')"); |
| |
| // Not testing rename partition, exchange partition, msck repair, archive/unarchive, |
| // set location, enable/disable no_drop/offline, compact (because not everyone may have |
| // ACID on), change column |
| |
| stmt.execute("drop table " + table1); |
| |
| } |
| } |
| |
| @Test |
| public void view() throws SQLException { |
| final String table1 = "odpi_sql_vtable1"; |
| final String view1 = "odpi_sql_view1"; |
| final String view2 = "odpi_sql_view2"; |
| try (Statement stmt = conn.createStatement()) { |
| stmt.execute("drop table if exists " + table1); |
| stmt.execute("drop view if exists " + view1); |
| stmt.execute("drop view if exists " + view2); |
| stmt.execute("create table " + table1 + "(a int, b varchar(32))"); |
| stmt.execute("create view " + view1 + " as select a from " + table1); |
| |
| stmt.execute("create view if not exists " + view2 + |
| " comment 'a view comment' " + |
| "tblproperties ('a' = 'b') " + |
| "as select b from " + table1); |
| |
| stmt.execute("alter view " + view1 + " as select a, b from " + table1); |
| stmt.execute("alter view " + view2 + " set tblproperties('c' = 'd')"); |
| |
| stmt.execute("drop view " + view1); |
| stmt.execute("drop view " + view2); |
| } |
| } |
| |
| // Not testing indices because they are currently useless in Hive |
| // Not testing macros because as far as I know no one uses them |
| |
| @Test |
| public void function() throws SQLException { |
| final String func1 = "odpi_sql_func1"; |
| final String func2 = "odpi_sql_func2"; |
| try (Statement stmt = conn.createStatement()) { |
| stmt.execute("create temporary function " + func1 + |
| " as 'org.apache.hadoop.hive.ql.udf.UDFToInteger'"); |
| stmt.execute("drop temporary function " + func1); |
| |
| stmt.execute("drop function if exists " + func2); |
| |
| stmt.execute("create function " + func2 + |
| " as 'org.apache.hadoop.hive.ql.udf.UDFToInteger'"); |
| stmt.execute("drop function " + func2); |
| } |
| } |
| |
| // Not testing grant/revoke/roles as different vendors use different security solutions |
| // and hence different things will work here. |
| |
| // This covers insert (non-partitioned, partitioned, dynamic partitions, overwrite, with |
| // values and select), and multi-insert. Load is not tested as there's no guarantee that the |
| // test machine has access to HDFS and thus the ability to upload a file. |
| @Test |
| public void insert() throws SQLException { |
| final String table1 = "odpi_insert_table1"; |
| final String table2 = "odpi_insert_table2"; |
| try (Statement stmt = conn.createStatement()) { |
| stmt.execute("drop table if exists " + table1); |
| stmt.execute("create table " + table1 + |
| "(c1 tinyint," + |
| " c2 smallint," + |
| " c3 int," + |
| " c4 bigint," + |
| " c5 float," + |
| " c6 double," + |
| " c7 decimal(8,2)," + |
| " c8 varchar(120)," + |
| " c9 char(10)," + |
| " c10 boolean)" + |
| " partitioned by (p1 string)"); |
| |
| // insert with partition |
| stmt.execute("explain insert into " + table1 + " partition (p1 = 'a') values " + |
| "(1, 2, 3, 4, 1.1, 2.2, 3.3, 'abcdef', 'ghi', true)," + |
| "(5, 6, 7, 8, 9.9, 8.8, 7.7, 'jklmno', 'pqr', true)"); |
| |
| stmt.execute("set hive.exec.dynamic.partition.mode=nonstrict"); |
| |
| // dynamic partition |
| stmt.execute("explain insert into " + table1 + " partition (p1) values " + |
| "(1, 2, 3, 4, 1.1, 2.2, 3.3, 'abcdef', 'ghi', true, 'b')," + |
| "(5, 6, 7, 8, 9.9, 8.8, 7.7, 'jklmno', 'pqr', true, 'b')"); |
| |
| stmt.execute("drop table if exists " + table2); |
| |
| stmt.execute("create table " + table2 + |
| "(c1 tinyint," + |
| " c2 smallint," + |
| " c3 int," + |
| " c4 bigint," + |
| " c5 float," + |
| " c6 double," + |
| " c7 decimal(8,2)," + |
| " c8 varchar(120)," + |
| " c9 char(10)," + |
| " c10 boolean)"); |
| |
| stmt.execute("explain insert into " + table2 + " values " + |
| "(1, 2, 3, 4, 1.1, 2.2, 3.3, 'abcdef', 'ghi', true)," + |
| "(5, 6, 7, 8, 9.9, 8.8, 7.7, 'jklmno', 'pqr', true)"); |
| |
| stmt.execute("explain insert overwrite table " + table2 + " select c1, c2, c3, c4, c5, c6, " + |
| "c7, c8, c9, c10 from " + table1); |
| |
| // multi-insert |
| stmt.execute("from " + table1 + |
| " insert into table " + table1 + " partition (p1 = 'c') " + |
| " select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10" + |
| " insert into table " + table2 + " select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10"); |
| } |
| } |
| |
| // This tests CTEs |
| @Test |
| public void cte() throws SQLException { |
| final String table1 = "odpi_cte_table1"; |
| try (Statement stmt = conn.createStatement()) { |
| stmt.execute("drop table if exists " + table1); |
| stmt.execute("create table " + table1 + "(c1 int, c2 varchar(32))"); |
| stmt.execute("with cte1 as (select c1 from " + table1 + " where c1 < 10) " + |
| " select c1 from cte1"); |
| } |
| } |
| |
| // This tests select, including CTEs, all/distinct, single tables, joins (inner & outer), |
| // group by (w/ and w/o having), order by, cluster by/distribute by/sort by, limit, union, |
| // subqueries, and over. |
| |
| @Test |
| public void select() throws SQLException { |
| final String[] tables = {"odpi_select_table1", "odpi_select_table2"}; |
| try (Statement stmt = conn.createStatement()) { |
| for (int i = 0; i < tables.length; i++) { |
| stmt.execute("drop table if exists " + tables[i]); |
| stmt.execute("create table " + tables[i] + "(c1 int, c2 varchar(32))"); |
| } |
| |
| // single table queries tested above in several places |
| |
| stmt.execute("explain select all a.c2, SUM(a.c1), SUM(b.c1) " + |
| "from " + tables[0] + " a join " + tables[1] + " b on (a.c2 = b.c2) " + |
| "group by a.c2 " + |
| "order by a.c2 asc " + |
| "limit 10"); |
| |
| stmt.execute("explain select distinct a.c2 " + |
| "from " + tables[0] + " a left outer join " + tables[1] + " b on (a.c2 = b.c2) " + |
| "order by a.c2 desc "); |
| |
| stmt.execute("explain select a.c2, SUM(a.c1) " + |
| "from " + tables[0] + " a right outer join " + tables[1] + " b on (a.c2 = b.c2) " + |
| "group by a.c2 " + |
| "having SUM(b.c1) > 0 " + |
| "order by a.c2 "); |
| |
| stmt.execute("explain select a.c2, rank() over (partition by a.c1) " + |
| "from " + tables[0] + " a full outer join " + tables[1] + " b on (a.c2 = b.c2) "); |
| |
| stmt.execute("explain select c2 from " + tables[0] + " union all select c2 from " + tables[1]); |
| |
| stmt.execute("explain select * from " + tables[0] + " distribute by c1 sort by c2"); |
| stmt.execute("explain select * from " + tables[0] + " cluster by c1"); |
| |
| stmt.execute("explain select * from (select c1 from " + tables[0] + ") t"); |
| stmt.execute("explain select * from " + tables[0] + " where c1 in (select c1 from " + tables[1] + |
| ")"); |
| |
| } |
| |
| } |
| |
| // Update and delete are not tested because not everyone configures their system to run |
| // with ACID. |
| |
| |
| } |
| |
| |
| |
| |
| |