From a6d5da676ebd34df5c38b6c3bbf1987264e6a062 Mon Sep 17 00:00:00 2001 From: Soumyakanti Das Date: Wed, 26 Aug 2026 10:58:59 -0700 Subject: [PATCH] HIVE-29308: Exception when JDBC table names are case-sensitive --- ...t_case_sensitive_country_table.mariadb.sql | 21 ++++ ...est_case_sensitive_country_table.mssql.sql | 24 ++++ ...est_case_sensitive_country_table.mysql.sql | 19 +++ ...st_case_sensitive_country_table.oracle.sql | 25 ++++ ..._case_sensitive_country_table.postgres.sql | 21 ++++ .../hive/storage/jdbc/JdbcStorageHandler.java | 20 +++- .../jdbc/TestJdbcStorageHandlerAuthUri.java | 85 ++++++++++++++ .../apache/hadoop/hive/ql/exec/Utilities.java | 30 +++++ .../hadoop/hive/ql/parse/CalcitePlanner.java | 6 +- .../hadoop/hive/ql/exec/TestUtilities.java | 44 +++++++ .../jdbc_case_sensitive_table_mariadb.q | 30 +++++ .../jdbc_case_sensitive_table_mssql.q | 31 +++++ .../jdbc_case_sensitive_table_mysql.q | 30 +++++ .../jdbc_case_sensitive_table_oracle.q | 33 ++++++ .../jdbc_case_sensitive_table_postgres.q | 35 ++++++ .../jdbc_case_sensitive_table_mariadb.q.out | 106 +++++++++++++++++ .../jdbc_case_sensitive_table_mssql.q.out | 100 ++++++++++++++++ .../jdbc_case_sensitive_table_mysql.q.out | 106 +++++++++++++++++ .../jdbc_case_sensitive_table_oracle.q.out | 110 ++++++++++++++++++ .../jdbc_case_sensitive_table_postgres.q.out | 110 ++++++++++++++++++ 20 files changed, 980 insertions(+), 6 deletions(-) create mode 100644 data/scripts/q_test_case_sensitive_country_table.mariadb.sql create mode 100644 data/scripts/q_test_case_sensitive_country_table.mssql.sql create mode 100644 data/scripts/q_test_case_sensitive_country_table.mysql.sql create mode 100644 data/scripts/q_test_case_sensitive_country_table.oracle.sql create mode 100644 data/scripts/q_test_case_sensitive_country_table.postgres.sql create mode 100644 jdbc-handler/src/test/java/org/apache/hive/storage/jdbc/TestJdbcStorageHandlerAuthUri.java create mode 100644 ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mariadb.q create mode 100644 ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mssql.q create mode 100644 ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mysql.q create mode 100644 ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_oracle.q create mode 100644 ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_postgres.q create mode 100644 ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mariadb.q.out create mode 100644 ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mssql.q.out create mode 100644 ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mysql.q.out create mode 100644 ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_oracle.q.out create mode 100644 ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_postgres.q.out diff --git a/data/scripts/q_test_case_sensitive_country_table.mariadb.sql b/data/scripts/q_test_case_sensitive_country_table.mariadb.sql new file mode 100644 index 000000000000..4739912abc3f --- /dev/null +++ b/data/scripts/q_test_case_sensitive_country_table.mariadb.sql @@ -0,0 +1,21 @@ +-- country and `Country` are distinct tables. +CREATE SCHEMA bob; + +CREATE TABLE bob.country +( + id int, + name varchar(20) +); +insert into bob.country values (1, 'India'); +insert into bob.country values (2, 'Russia'); +insert into bob.country values (3, 'USA'); + +CREATE TABLE bob.`Country` +( + id int, + name varchar(20) +); +insert into bob.`Country` values (10, 'Italy'); +insert into bob.`Country` values (11, 'Greece'); + + diff --git a/data/scripts/q_test_case_sensitive_country_table.mssql.sql b/data/scripts/q_test_case_sensitive_country_table.mssql.sql new file mode 100644 index 000000000000..17744b826244 --- /dev/null +++ b/data/scripts/q_test_case_sensitive_country_table.mssql.sql @@ -0,0 +1,24 @@ +-- A case-sensitive collation makes country and [Country] distinct tables. +CREATE DATABASE worldcs COLLATE Latin1_General_CS_AS; +USE worldcs; + +CREATE SCHEMA bob; + +CREATE TABLE bob.country +( + id int, + name varchar(20) +); +insert into bob.country values (1, 'India'); +insert into bob.country values (2, 'Russia'); +insert into bob.country values (3, 'USA'); + +CREATE TABLE bob.[Country] +( + id int, + name varchar(20) +); +insert into bob.[Country] values (10, 'Italy'); +insert into bob.[Country] values (11, 'Greece'); + + diff --git a/data/scripts/q_test_case_sensitive_country_table.mysql.sql b/data/scripts/q_test_case_sensitive_country_table.mysql.sql new file mode 100644 index 000000000000..51148d856431 --- /dev/null +++ b/data/scripts/q_test_case_sensitive_country_table.mysql.sql @@ -0,0 +1,19 @@ +-- country and `Country` are distinct tables. +CREATE TABLE country +( + id int, + name varchar(20) +); +insert into country values (1, 'India'); +insert into country values (2, 'Russia'); +insert into country values (3, 'USA'); + +CREATE TABLE `Country` +( + id int, + name varchar(20) +); +insert into `Country` values (10, 'Italy'); +insert into `Country` values (11, 'Greece'); + + diff --git a/data/scripts/q_test_case_sensitive_country_table.oracle.sql b/data/scripts/q_test_case_sensitive_country_table.oracle.sql new file mode 100644 index 000000000000..f72f6091d66c --- /dev/null +++ b/data/scripts/q_test_case_sensitive_country_table.oracle.sql @@ -0,0 +1,25 @@ +-- country (unquoted, folded to COUNTRY) and "Country" (quoted, case-sensitive) are distinct tables. +ALTER SESSION SET CONTAINER = XEPDB1; + +CREATE USER bob IDENTIFIED BY bobpass; +ALTER USER bob QUOTA UNLIMITED ON users; +GRANT CREATE SESSION TO bob; + +CREATE TABLE bob.country +( + id int, + name varchar(20) +); +insert into bob.country values (1, 'India'); +insert into bob.country values (2, 'Russia'); +insert into bob.country values (3, 'USA'); + +CREATE TABLE bob."Country" +( + id int, + name varchar(20) +); +insert into bob."Country" values (10, 'Italy'); +insert into bob."Country" values (11, 'Greece'); + + diff --git a/data/scripts/q_test_case_sensitive_country_table.postgres.sql b/data/scripts/q_test_case_sensitive_country_table.postgres.sql new file mode 100644 index 000000000000..959054f0cb62 --- /dev/null +++ b/data/scripts/q_test_case_sensitive_country_table.postgres.sql @@ -0,0 +1,21 @@ +-- country (unquoted, lowercase) and "Country" (quoted, case-sensitive) are distinct tables. +CREATE SCHEMA bob; + +CREATE TABLE bob.country +( + id int, + name varchar(20) +); +insert into bob.country values (1, 'India'); +insert into bob.country values (2, 'Russia'); +insert into bob.country values (3, 'USA'); + +CREATE TABLE bob."Country" +( + id int, + name varchar(20) +); +insert into bob."Country" values (10, 'Italy'); +insert into bob."Country" values (11, 'Greece'); + + diff --git a/jdbc-handler/src/main/java/org/apache/hive/storage/jdbc/JdbcStorageHandler.java b/jdbc-handler/src/main/java/org/apache/hive/storage/jdbc/JdbcStorageHandler.java index 539a26514ae4..82a04421b8e3 100644 --- a/jdbc-handler/src/main/java/org/apache/hive/storage/jdbc/JdbcStorageHandler.java +++ b/jdbc-handler/src/main/java/org/apache/hive/storage/jdbc/JdbcStorageHandler.java @@ -41,6 +41,8 @@ import java.io.IOException; import java.lang.IllegalArgumentException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -48,6 +50,8 @@ import java.net.URI; import java.net.URISyntaxException; +import static org.apache.hadoop.hive.ql.exec.Utilities.unquoteJdbcIdentifier; + public class JdbcStorageHandler implements HiveStorageHandler { private static final Logger LOGGER = LoggerFactory.getLogger(JdbcStorageHandler.class); @@ -107,10 +111,20 @@ public URI getURIForAuth(Table table) throws URISyntaxException { Map tableProperties = HiveCustomStorageHandlerUtils.getTableProperties(table); DatabaseType dbType = DatabaseType.valueOf( tableProperties.get(JdbcStorageConfig.DATABASE_TYPE.getPropertyName())); - String host_url = DatabaseType.METASTORE == dbType ? + String hostUrl = DatabaseType.METASTORE == dbType ? "jdbc:metastore://" : tableProperties.get(Constants.JDBC_URL); - String table_name = tableProperties.get(Constants.JDBC_TABLE); - return new URI(host_url+"/"+table_name); + // Encode only the auth-resource path segment to keep URI construction valid; this does not + // alter the JDBC URL used by the driver for actual query execution. + String tableName = encodeIdentifierForAuth(tableProperties.get(Constants.JDBC_TABLE)); + return new URI(hostUrl + "/" + tableName); + } + + private static String encodeIdentifierForAuth(String identifier) { + String physical = unquoteJdbcIdentifier(identifier); + if (physical == null) { + return null; + } + return URLEncoder.encode(physical, StandardCharsets.UTF_8); } @Override diff --git a/jdbc-handler/src/test/java/org/apache/hive/storage/jdbc/TestJdbcStorageHandlerAuthUri.java b/jdbc-handler/src/test/java/org/apache/hive/storage/jdbc/TestJdbcStorageHandlerAuthUri.java new file mode 100644 index 000000000000..a16b7259ec6f --- /dev/null +++ b/jdbc-handler/src/test/java/org/apache/hive/storage/jdbc/TestJdbcStorageHandlerAuthUri.java @@ -0,0 +1,85 @@ +/* + * Licensed 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.hive.storage.jdbc; + +import org.apache.hadoop.hive.metastore.api.SerDeInfo; +import org.apache.hadoop.hive.metastore.api.StorageDescriptor; +import org.apache.hadoop.hive.metastore.api.Table; +import org.junit.Test; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * Unit tests for {@link JdbcStorageHandler#getURIForAuth(Table)} + */ +public class TestJdbcStorageHandlerAuthUri { + + private static Table tableWith(Map params) { + Table table = new Table(); + table.setParameters(params); + StorageDescriptor sd = new StorageDescriptor(); + sd.setSerdeInfo(new SerDeInfo("serde", "serde.lib", new HashMap<>())); + table.setSd(sd); + return table; + } + + private URI authUri(String jdbcUrl, String schema, String table) throws URISyntaxException { + Map params = new HashMap<>(); + params.put("hive.sql.database.type", "POSTGRES"); + params.put("hive.sql.jdbc.url", jdbcUrl); + if (schema != null) { + params.put("hive.sql.schema", schema); + } + if (table != null) { + params.put("hive.sql.table", table); + } + return new JdbcStorageHandler().getURIForAuth(tableWith(params)); + } + + @Test + public void testUnquotedTableUnchanged() throws Exception { + URI uri = authUri("jdbc:postgresql://host:5432/db", null, "country"); + assertEquals("jdbc:postgresql://host:5432/db/country", uri.toString()); + } + + @Test + public void testQuotedTableStripsQuotesPreservingCase() throws Exception { + URI uri = authUri("jdbc:postgresql://host:5432/db", null, "\"Country\""); + // The physical identifier keeps its original case, and the surrounding quotes are stripped. + assertEquals("jdbc:postgresql://host:5432/db/Country", uri.toString()); + } + + @Test + public void testQuotedTableWithSchemaOnlyEncodesTable() throws Exception { + // The historical authorization URI only contains the table name; the schema does not affect it. + URI uri = authUri("jdbc:postgresql://host:5432/db", "\"World\"", "\"Country\""); + assertEquals("jdbc:postgresql://host:5432/db/Country", uri.toString()); + } + + @Test + public void testTableWithSpecialCharactersIsUriSafe() throws Exception { + // A quoted identifier may legally contain characters that are illegal in a raw URI; they must be encoded. + URI uri = authUri("jdbc:postgresql://host:5432/db", null, "\"Odd/Name\""); + // '/' -> %2F ; the resulting string is a valid URI. + assertEquals("jdbc:postgresql://host:5432/db/Odd%2FName", uri.toString()); + } +} + + + diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java index ea7603d39c7f..d72ff30aaafd 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java @@ -5151,4 +5151,34 @@ public static void setTableCreateTime(Configuration conf, Table table) { public static int getTableCreateTime(Configuration conf, String tableName) { return conf.getInt(String.format("%s.%s", tableName, CREATE_TIME), 0); } + + /** + * Returns the physical (unquoted) form of a JDBC identifier supplied through table properties such as + * {@code hive.sql.table} or {@code hive.sql.schema}, for use in contexts that need the identifier exactly as + * stored in the remote catalog (JDBC metadata lookups, Calcite resolution, authorization URIs). + * + *

Recognises ANSI/Oracle/Postgres double quotes ({@code "id"}), MySQL/MariaDB back-ticks ({@code `id`}) and + * SQL Server brackets ({@code [id]}). Unquoted identifiers are returned unchanged. + */ + public static String unquoteJdbcIdentifier(String identifier) { + if (identifier == null || identifier.length() < 2) { + return identifier; + } + char start = identifier.charAt(0); + char end = identifier.charAt(identifier.length() - 1); + final char closing; + if (start == '"' || start == '`') { + closing = start; + } else if (start == '[') { + closing = ']'; + } else { + return identifier; + } + if (end != closing) { + return identifier; + } + String inner = identifier.substring(1, identifier.length() - 1); + // A literal quote char inside a quoted identifier is escaped by doubling it. + return inner.replace(String.valueOf(closing) + closing, String.valueOf(closing)); + } } diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java index 6c9f412a1a5f..0b1adc200213 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java @@ -3056,9 +3056,9 @@ private RelNode genTableLogicalPlan(String tableAlias, QB qb) throws SemanticExc pswd = null; LOG.warn("No password found for accessing {} table via JDBC", fullyQualifiedTabName); } - final String catalogName = tabMetaData.getProperty(Constants.JDBC_CATALOG); - final String schemaName = tabMetaData.getProperty(Constants.JDBC_SCHEMA); - final String tableName = tabMetaData.getProperty(Constants.JDBC_TABLE); + final String catalogName = Utilities.unquoteJdbcIdentifier(tabMetaData.getProperty(Constants.JDBC_CATALOG)); + final String schemaName = Utilities.unquoteJdbcIdentifier(tabMetaData.getProperty(Constants.JDBC_SCHEMA)); + final String tableName = Utilities.unquoteJdbcIdentifier(tabMetaData.getProperty(Constants.JDBC_TABLE)); DataSource ds = JdbcSchema.dataSource(url, driver, user, pswd); SqlDialect jdbcDialect = JdbcSchema.createDialect(SqlDialectFactoryImpl.INSTANCE, ds); diff --git a/ql/src/test/org/apache/hadoop/hive/ql/exec/TestUtilities.java b/ql/src/test/org/apache/hadoop/hive/ql/exec/TestUtilities.java index b967f02c5ec1..f1e53f48b012 100644 --- a/ql/src/test/org/apache/hadoop/hive/ql/exec/TestUtilities.java +++ b/ql/src/test/org/apache/hadoop/hive/ql/exec/TestUtilities.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.apache.hadoop.hive.ql.exec.Utilities.getFileExtension; @@ -902,4 +903,47 @@ private Set getResultPathes(List foundManifestFiles) { } return resultPathes; } + + @Test + public void testUnquoteJdbcIdentifierNullAndShortInputsUnchanged() { + assertNull(Utilities.unquoteJdbcIdentifier(null)); + assertEquals("", Utilities.unquoteJdbcIdentifier("")); + // A single character cannot be a matched quote pair. + assertEquals("\"", Utilities.unquoteJdbcIdentifier("\"")); + } + + @Test + public void testUnquoteJdbcIdentifierUnquotedInputUnchanged() { + // Unquoted identifiers keep the current (case-insensitive) behaviour. + assertEquals("Country", Utilities.unquoteJdbcIdentifier("Country")); + assertEquals("country", Utilities.unquoteJdbcIdentifier("country")); + assertEquals("COUNTRY", Utilities.unquoteJdbcIdentifier("COUNTRY")); + } + + @Test + public void testUnquoteJdbcIdentifierStripsSupportedQuotePairs() { + // ANSI / Oracle / Postgres double quotes. + assertEquals("Country", Utilities.unquoteJdbcIdentifier("\"Country\"")); + // MySQL / MariaDB back-ticks. + assertEquals("Country", Utilities.unquoteJdbcIdentifier("`Country`")); + // SQL Server brackets. + assertEquals("Country", Utilities.unquoteJdbcIdentifier("[Country]")); + // Schema-style identifiers with mixed case are preserved after unquoting. + assertEquals("WorldData", Utilities.unquoteJdbcIdentifier("\"WorldData\"")); + } + + @Test + public void testUnquoteJdbcIdentifierUnescapesDoubledQuotes() { + assertEquals("a\"b", Utilities.unquoteJdbcIdentifier("\"a\"\"b\"")); + assertEquals("a`b", Utilities.unquoteJdbcIdentifier("`a``b`")); + assertEquals("a]b", Utilities.unquoteJdbcIdentifier("[a]]b]")); + } + + @Test + public void testUnquoteJdbcIdentifierUnbalancedQuotesUnchanged() { + assertEquals("\"Country", Utilities.unquoteJdbcIdentifier("\"Country")); + assertEquals("Country\"", Utilities.unquoteJdbcIdentifier("Country\"")); + assertEquals("[Country", Utilities.unquoteJdbcIdentifier("[Country")); + assertEquals("\"Country`", Utilities.unquoteJdbcIdentifier("\"Country`")); + } } diff --git a/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mariadb.q b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mariadb.q new file mode 100644 index 000000000000..223091b69d82 --- /dev/null +++ b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mariadb.q @@ -0,0 +1,30 @@ +--! qt:database:mariadb:qdb:q_test_case_sensitive_country_table.mariadb.sql + +CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "org.mariadb.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mariadb://${system:hive.test.database.qdb.host}:${system:hive.test.database.qdb.port}/bob", + "hive.sql.dbcp.username" = "${system:hive.test.database.qdb.jdbc.username}", + "hive.sql.dbcp.password" = "${system:hive.test.database.qdb.jdbc.password}", + "hive.sql.table" = "country"); + +EXPLAIN CBO SELECT COUNT(*) FROM country_lower; +SELECT COUNT(*) FROM country_lower; + +-- The back-tick quoted mixed-case table must resolve to `Country` (2 rows). +CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "org.mariadb.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mariadb://${system:hive.test.database.qdb.host}:${system:hive.test.database.qdb.port}/bob", + "hive.sql.dbcp.username" = "${system:hive.test.database.qdb.jdbc.username}", + "hive.sql.dbcp.password" = "${system:hive.test.database.qdb.jdbc.password}", + "hive.sql.table" = "`Country`"); + +EXPLAIN CBO SELECT COUNT(*) FROM country_mixed; +SELECT COUNT(*) FROM country_mixed; +SELECT * FROM country_mixed ORDER BY id; + diff --git a/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mssql.q b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mssql.q new file mode 100644 index 000000000000..00a58727e809 --- /dev/null +++ b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mssql.q @@ -0,0 +1,31 @@ +--! qt:database:mssql:qdb:q_test_case_sensitive_country_table.mssql.sql + +CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MSSQL", + "hive.sql.jdbc.driver" = "com.microsoft.sqlserver.jdbc.SQLServerDriver", + "hive.sql.jdbc.url" = "${system:hive.test.database.qdb.jdbc.url};DatabaseName=worldcs;", + "hive.sql.dbcp.username" = "${system:hive.test.database.qdb.jdbc.username}", + "hive.sql.dbcp.password" = "${system:hive.test.database.qdb.jdbc.password}", + "hive.sql.schema" = "bob", + "hive.sql.table" = "country"); + +EXPLAIN CBO SELECT COUNT(*) FROM country_lower; +SELECT COUNT(*) FROM country_lower; + +-- The bracket-quoted mixed-case table must resolve to bob.[Country] (2 rows). +CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MSSQL", + "hive.sql.jdbc.driver" = "com.microsoft.sqlserver.jdbc.SQLServerDriver", + "hive.sql.jdbc.url" = "${system:hive.test.database.qdb.jdbc.url};DatabaseName=worldcs;", + "hive.sql.dbcp.username" = "${system:hive.test.database.qdb.jdbc.username}", + "hive.sql.dbcp.password" = "${system:hive.test.database.qdb.jdbc.password}", + "hive.sql.schema" = "bob", + "hive.sql.table" = "[Country]"); + +EXPLAIN CBO SELECT COUNT(*) FROM country_mixed; +SELECT COUNT(*) FROM country_mixed; + diff --git a/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mysql.q b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mysql.q new file mode 100644 index 000000000000..c977d9d24daa --- /dev/null +++ b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_mysql.q @@ -0,0 +1,30 @@ +--! qt:database:mysql:qdb:q_test_case_sensitive_country_table.mysql.sql + +CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "com.mysql.jdbc.Driver", + "hive.sql.jdbc.url" = "${system:hive.test.database.qdb.jdbc.url}", + "hive.sql.dbcp.username" = "${system:hive.test.database.qdb.jdbc.username}", + "hive.sql.dbcp.password" = "${system:hive.test.database.qdb.jdbc.password}", + "hive.sql.table" = "country"); + +EXPLAIN CBO SELECT COUNT(*) FROM country_lower; +SELECT COUNT(*) FROM country_lower; + +-- The back-tick quoted mixed-case table must resolve to `Country` (2 rows). +CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "com.mysql.jdbc.Driver", + "hive.sql.jdbc.url" = "${system:hive.test.database.qdb.jdbc.url}", + "hive.sql.dbcp.username" = "${system:hive.test.database.qdb.jdbc.username}", + "hive.sql.dbcp.password" = "${system:hive.test.database.qdb.jdbc.password}", + "hive.sql.table" = "`Country`"); + +EXPLAIN CBO SELECT COUNT(*) FROM country_mixed; +SELECT COUNT(*) FROM country_mixed; +SELECT * FROM country_mixed ORDER BY id; + diff --git a/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_oracle.q b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_oracle.q new file mode 100644 index 000000000000..5d15297a550b --- /dev/null +++ b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_oracle.q @@ -0,0 +1,33 @@ +--! qt:database:oracle:qdb:q_test_case_sensitive_country_table.oracle.sql +-- Oracle folds unquoted identifiers to uppercase and preserves quoted ones verbatim. + +CREATE EXTERNAL TABLE country_upper (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "ORACLE", + "hive.sql.jdbc.driver" = "oracle.jdbc.OracleDriver", + "hive.sql.jdbc.url" = "jdbc:oracle:thin:@//${system:hive.test.database.qdb.host}:${system:hive.test.database.qdb.port}/XEPDB1", + "hive.sql.dbcp.username" = "bob", + "hive.sql.dbcp.password" = "bobpass", + "hive.sql.schema" = "BOB", + "hive.sql.table" = "COUNTRY"); + +EXPLAIN CBO SELECT COUNT(*) FROM country_upper; +SELECT COUNT(*) FROM country_upper; + +-- The quoted mixed-case table must resolve to bob."Country" (2 rows). +CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "ORACLE", + "hive.sql.jdbc.driver" = "oracle.jdbc.OracleDriver", + "hive.sql.jdbc.url" = "jdbc:oracle:thin:@//${system:hive.test.database.qdb.host}:${system:hive.test.database.qdb.port}/XEPDB1", + "hive.sql.dbcp.username" = "bob", + "hive.sql.dbcp.password" = "bobpass", + "hive.sql.schema" = "BOB", + "hive.sql.table" = '"Country"'); + +EXPLAIN CBO SELECT COUNT(*) FROM country_mixed; +SELECT COUNT(*) FROM country_mixed; +SELECT * FROM country_mixed ORDER BY id; + diff --git a/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_postgres.q b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_postgres.q new file mode 100644 index 000000000000..595119a790e3 --- /dev/null +++ b/ql/src/test/queries/clientpositive/jdbc_case_sensitive_table_postgres.q @@ -0,0 +1,35 @@ +--! qt:database:postgres:qdb:q_test_case_sensitive_country_table.postgres.sql +-- Postgres folds unquoted identifiers to lowercase and preserves quoted ones verbatim. + +CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "POSTGRES", + "hive.sql.jdbc.driver" = "org.postgresql.Driver", + "hive.sql.jdbc.url" = "${system:hive.test.database.qdb.jdbc.url}", + "hive.sql.dbcp.username" = "${system:hive.test.database.qdb.jdbc.username}", + "hive.sql.dbcp.password" = "${system:hive.test.database.qdb.jdbc.password}", + "hive.sql.schema" = "bob", + "hive.sql.table" = "country"); + +EXPLAIN CBO SELECT COUNT(*) FROM country_lower; +SELECT COUNT(*) FROM country_lower; + +-- The quoted mixed-case table must resolve to bob."Country" (2 rows), not bob.country. +CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "POSTGRES", + "hive.sql.jdbc.driver" = "org.postgresql.Driver", + "hive.sql.jdbc.url" = "${system:hive.test.database.qdb.jdbc.url}", + "hive.sql.dbcp.username" = "${system:hive.test.database.qdb.jdbc.username}", + "hive.sql.dbcp.password" = "${system:hive.test.database.qdb.jdbc.password}", + "hive.sql.schema" = "bob", + "hive.sql.table" = '"Country"'); + +EXPLAIN CBO SELECT COUNT(*) FROM country_mixed; +SELECT COUNT(*) FROM country_mixed; +SELECT * FROM country_mixed ORDER BY id; + + + diff --git a/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mariadb.q.out b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mariadb.q.out new file mode 100644 index 000000000000..89e973a3715e --- /dev/null +++ b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mariadb.q.out @@ -0,0 +1,106 @@ +PREHOOK: query: CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "org.mariadb.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mariadb://localhost:3309/bob", + "hive.sql.dbcp.username" = "root", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.table" = "country") +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_lower +POSTHOOK: query: CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "org.mariadb.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mariadb://localhost:3309/bob", + "hive.sql.dbcp.username" = "root", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.table" = "country") +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_lower +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_lower +PREHOOK: type: QUERY +PREHOOK: Input: default@country_lower +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_lower +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_lower +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.MYSQL]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_lower]], table:alias=[country_lower]) + +PREHOOK: query: SELECT COUNT(*) FROM country_lower +PREHOOK: type: QUERY +PREHOOK: Input: default@country_lower +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_lower +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_lower +#### A masked pattern was here #### +3 +PREHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "org.mariadb.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mariadb://localhost:3309/bob", + "hive.sql.dbcp.username" = "root", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.table" = "`Country`") +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_mixed +POSTHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "org.mariadb.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mariadb://localhost:3309/bob", + "hive.sql.dbcp.username" = "root", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.table" = "`Country`") +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_mixed +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.MYSQL]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_mixed]], table:alias=[country_mixed]) + +PREHOOK: query: SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +2 +PREHOOK: query: SELECT * FROM country_mixed ORDER BY id +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: SELECT * FROM country_mixed ORDER BY id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +10 Italy +11 Greece diff --git a/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mssql.q.out b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mssql.q.out new file mode 100644 index 000000000000..70cbc91cb77f --- /dev/null +++ b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mssql.q.out @@ -0,0 +1,100 @@ +PREHOOK: query: CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MSSQL", + "hive.sql.jdbc.driver" = "com.microsoft.sqlserver.jdbc.SQLServerDriver", + "hive.sql.jdbc.url" = "jdbc:sqlserver://localhost:1433;DatabaseName=worldcs;", + "hive.sql.dbcp.username" = "sa", + "hive.sql.dbcp.password" = "Its-a-s3cret", + "hive.sql.schema" = "bob", + "hive.sql.table" = "country") +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_lower +POSTHOOK: query: CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MSSQL", + "hive.sql.jdbc.driver" = "com.microsoft.sqlserver.jdbc.SQLServerDriver", + "hive.sql.jdbc.url" = "jdbc:sqlserver://localhost:1433;DatabaseName=worldcs;", + "hive.sql.dbcp.username" = "sa", + "hive.sql.dbcp.password" = "Its-a-s3cret", + "hive.sql.schema" = "bob", + "hive.sql.table" = "country") +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_lower +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_lower +PREHOOK: type: QUERY +PREHOOK: Input: default@country_lower +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_lower +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_lower +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.MSSQL]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_lower]], table:alias=[country_lower]) + +PREHOOK: query: SELECT COUNT(*) FROM country_lower +PREHOOK: type: QUERY +PREHOOK: Input: default@country_lower +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_lower +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_lower +#### A masked pattern was here #### +3 +PREHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MSSQL", + "hive.sql.jdbc.driver" = "com.microsoft.sqlserver.jdbc.SQLServerDriver", + "hive.sql.jdbc.url" = "jdbc:sqlserver://localhost:1433;DatabaseName=worldcs;", + "hive.sql.dbcp.username" = "sa", + "hive.sql.dbcp.password" = "Its-a-s3cret", + "hive.sql.schema" = "bob", + "hive.sql.table" = "[Country]") +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_mixed +POSTHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MSSQL", + "hive.sql.jdbc.driver" = "com.microsoft.sqlserver.jdbc.SQLServerDriver", + "hive.sql.jdbc.url" = "jdbc:sqlserver://localhost:1433;DatabaseName=worldcs;", + "hive.sql.dbcp.username" = "sa", + "hive.sql.dbcp.password" = "Its-a-s3cret", + "hive.sql.schema" = "bob", + "hive.sql.table" = "[Country]") +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_mixed +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.MSSQL]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_mixed]], table:alias=[country_mixed]) + +PREHOOK: query: SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +2 diff --git a/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mysql.q.out b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mysql.q.out new file mode 100644 index 000000000000..2963f8a25d0c --- /dev/null +++ b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_mysql.q.out @@ -0,0 +1,106 @@ +PREHOOK: query: CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "com.mysql.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mysql://localhost:3306/qdb", + "hive.sql.dbcp.username" = "root", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.table" = "country") +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_lower +POSTHOOK: query: CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "com.mysql.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mysql://localhost:3306/qdb", + "hive.sql.dbcp.username" = "root", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.table" = "country") +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_lower +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_lower +PREHOOK: type: QUERY +PREHOOK: Input: default@country_lower +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_lower +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_lower +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.MYSQL]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_lower]], table:alias=[country_lower]) + +PREHOOK: query: SELECT COUNT(*) FROM country_lower +PREHOOK: type: QUERY +PREHOOK: Input: default@country_lower +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_lower +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_lower +#### A masked pattern was here #### +3 +PREHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "com.mysql.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mysql://localhost:3306/qdb", + "hive.sql.dbcp.username" = "root", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.table" = "`Country`") +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_mixed +POSTHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "MYSQL", + "hive.sql.jdbc.driver" = "com.mysql.jdbc.Driver", + "hive.sql.jdbc.url" = "jdbc:mysql://localhost:3306/qdb", + "hive.sql.dbcp.username" = "root", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.table" = "`Country`") +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_mixed +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.MYSQL]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_mixed]], table:alias=[country_mixed]) + +PREHOOK: query: SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +2 +PREHOOK: query: SELECT * FROM country_mixed ORDER BY id +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: SELECT * FROM country_mixed ORDER BY id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +10 Italy +11 Greece diff --git a/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_oracle.q.out b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_oracle.q.out new file mode 100644 index 000000000000..9ab0fd29afe5 --- /dev/null +++ b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_oracle.q.out @@ -0,0 +1,110 @@ +PREHOOK: query: CREATE EXTERNAL TABLE country_upper (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "ORACLE", + "hive.sql.jdbc.driver" = "oracle.jdbc.OracleDriver", + "hive.sql.jdbc.url" = "jdbc:oracle:thin:@//localhost:1521/XEPDB1", + "hive.sql.dbcp.username" = "bob", + "hive.sql.dbcp.password" = "bobpass", + "hive.sql.schema" = "BOB", + "hive.sql.table" = "COUNTRY") +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_upper +POSTHOOK: query: CREATE EXTERNAL TABLE country_upper (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "ORACLE", + "hive.sql.jdbc.driver" = "oracle.jdbc.OracleDriver", + "hive.sql.jdbc.url" = "jdbc:oracle:thin:@//localhost:1521/XEPDB1", + "hive.sql.dbcp.username" = "bob", + "hive.sql.dbcp.password" = "bobpass", + "hive.sql.schema" = "BOB", + "hive.sql.table" = "COUNTRY") +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_upper +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_upper +PREHOOK: type: QUERY +PREHOOK: Input: default@country_upper +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_upper +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_upper +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.ORACLE]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_upper]], table:alias=[country_upper]) + +PREHOOK: query: SELECT COUNT(*) FROM country_upper +PREHOOK: type: QUERY +PREHOOK: Input: default@country_upper +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_upper +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_upper +#### A masked pattern was here #### +3 +PREHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "ORACLE", + "hive.sql.jdbc.driver" = "oracle.jdbc.OracleDriver", + "hive.sql.jdbc.url" = "jdbc:oracle:thin:@//localhost:1521/XEPDB1", + "hive.sql.dbcp.username" = "bob", + "hive.sql.dbcp.password" = "bobpass", + "hive.sql.schema" = "BOB", + "hive.sql.table" = '"Country"') +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_mixed +POSTHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "ORACLE", + "hive.sql.jdbc.driver" = "oracle.jdbc.OracleDriver", + "hive.sql.jdbc.url" = "jdbc:oracle:thin:@//localhost:1521/XEPDB1", + "hive.sql.dbcp.username" = "bob", + "hive.sql.dbcp.password" = "bobpass", + "hive.sql.schema" = "BOB", + "hive.sql.table" = '"Country"') +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_mixed +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.ORACLE]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_mixed]], table:alias=[country_mixed]) + +PREHOOK: query: SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +2 +PREHOOK: query: SELECT * FROM country_mixed ORDER BY id +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: SELECT * FROM country_mixed ORDER BY id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +10 Italy +11 Greece diff --git a/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_postgres.q.out b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_postgres.q.out new file mode 100644 index 000000000000..20173ec060c6 --- /dev/null +++ b/ql/src/test/results/clientpositive/llap/jdbc_case_sensitive_table_postgres.q.out @@ -0,0 +1,110 @@ +PREHOOK: query: CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "POSTGRES", + "hive.sql.jdbc.driver" = "org.postgresql.Driver", + "hive.sql.jdbc.url" = "jdbc:postgresql://localhost:5432/qdb", + "hive.sql.dbcp.username" = "qtestuser", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.schema" = "bob", + "hive.sql.table" = "country") +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_lower +POSTHOOK: query: CREATE EXTERNAL TABLE country_lower (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "POSTGRES", + "hive.sql.jdbc.driver" = "org.postgresql.Driver", + "hive.sql.jdbc.url" = "jdbc:postgresql://localhost:5432/qdb", + "hive.sql.dbcp.username" = "qtestuser", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.schema" = "bob", + "hive.sql.table" = "country") +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_lower +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_lower +PREHOOK: type: QUERY +PREHOOK: Input: default@country_lower +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_lower +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_lower +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.POSTGRES]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_lower]], table:alias=[country_lower]) + +PREHOOK: query: SELECT COUNT(*) FROM country_lower +PREHOOK: type: QUERY +PREHOOK: Input: default@country_lower +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_lower +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_lower +#### A masked pattern was here #### +3 +PREHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "POSTGRES", + "hive.sql.jdbc.driver" = "org.postgresql.Driver", + "hive.sql.jdbc.url" = "jdbc:postgresql://localhost:5432/qdb", + "hive.sql.dbcp.username" = "qtestuser", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.schema" = "bob", + "hive.sql.table" = '"Country"') +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@country_mixed +POSTHOOK: query: CREATE EXTERNAL TABLE country_mixed (id int, name varchar(20)) +STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler' +TBLPROPERTIES ( + "hive.sql.database.type" = "POSTGRES", + "hive.sql.jdbc.driver" = "org.postgresql.Driver", + "hive.sql.jdbc.url" = "jdbc:postgresql://localhost:5432/qdb", + "hive.sql.dbcp.username" = "qtestuser", + "hive.sql.dbcp.password" = "qtestpassword", + "hive.sql.schema" = "bob", + "hive.sql.table" = '"Country"') +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@country_mixed +PREHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN CBO SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +CBO PLAN: +HiveProject(_c0=[$0]) + HiveProject($f0=[$0]) + HiveJdbcConverter(convention=[JDBC.POSTGRES]) + JdbcAggregate(group=[{}], agg#0=[count()]) + JdbcHiveTableScan(table=[[default, country_mixed]], table:alias=[country_mixed]) + +PREHOOK: query: SELECT COUNT(*) FROM country_mixed +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: SELECT COUNT(*) FROM country_mixed +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +2 +PREHOOK: query: SELECT * FROM country_mixed ORDER BY id +PREHOOK: type: QUERY +PREHOOK: Input: default@country_mixed +#### A masked pattern was here #### +POSTHOOK: query: SELECT * FROM country_mixed ORDER BY id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@country_mixed +#### A masked pattern was here #### +10 Italy +11 Greece