Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for case sensitive identifiers #2350

Closed
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void setUp()
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add plenty of tests to BaseConnectorTest.

Things to cover:

  • whether output column aliases for remain their case
  • CREATE TABLE with case sensitive names
  • CREATE TABLE with columns that differs only with casing, do select, insert, update, delete from from that table
  • The similar like above with columns, but for schemas and catalogs.

queryRunner = LocalQueryRunner.create(testSessionBuilder()
.setCatalog("memory")
.setSchema("default")
.setSchema("DEFAULT")
.build());
queryRunner.installPlugin(new GeoPlugin());
queryRunner.createCatalog("memory", new MemoryConnectorFactory(), ImmutableMap.of());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public void setUp()
{
queryRunner = LocalQueryRunner.create(testSessionBuilder()
.setCatalog("memory")
.setSchema("default")
.setSchema("DEFAULT")
.build());
queryRunner.installPlugin(new GeoPlugin());
queryRunner.createCatalog("memory", new MemoryConnectorFactory(), ImmutableMap.of());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private static LocalQueryRunner createQueryRunner()
{
LocalQueryRunner queryRunner = LocalQueryRunner.create(testSessionBuilder()
.setCatalog("memory")
.setSchema("default")
.setSchema("DEFAULT")
.build());
queryRunner.installPlugin(new GeoPlugin());
queryRunner.createCatalog("tpch", new TpchConnectorFactory(1), ImmutableMap.of());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import static io.prestosql.spi.StandardErrorCode.SCHEMA_NOT_EMPTY;
import static io.prestosql.spi.connector.SampleType.SYSTEM;
import static java.lang.String.format;
import static java.util.Locale.ENGLISH;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
Expand All @@ -72,7 +73,7 @@
public class MemoryMetadata
implements ConnectorMetadata
{
public static final String SCHEMA_NAME = "default";
public static final String SCHEMA_NAME = "DEFAULT";

private final NodeManager nodeManager;
private final List<String> schemas = new ArrayList<>();
Expand Down Expand Up @@ -398,4 +399,10 @@ public Optional<ConnectorTableHandle> applySample(ConnectorSession session, Conn

return Optional.of(new MemoryTableHandle(table.getId(), table.getLimit(), OptionalDouble.of(table.getSampleRatio().orElse(1) * sampleRatio)));
}

@Override
public String canonicalize(ConnectorSession session, String identifier, boolean delimited)
{
return delimited ? identifier : identifier.toUpperCase(ENGLISH);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static DistributedQueryRunner createQueryRunner(Map<String, String> extra
{
Session session = testSessionBuilder()
.setCatalog(CATALOG)
.setSchema("default")
.setSchema("DEFAULT")
.build();

DistributedQueryRunner queryRunner = DistributedQueryRunner.builder(session)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void tableIsCreatedAfterCommits()
{
assertNoTables();

SchemaTableName schemaTableName = new SchemaTableName("default", "temp_table");
SchemaTableName schemaTableName = new SchemaTableName("DEFAULT", "temp_table");

ConnectorOutputTableHandle table = metadata.beginCreateTable(
SESSION,
Expand All @@ -79,8 +79,8 @@ public void tableAlreadyExists()
{
assertNoTables();

SchemaTableName test1Table = new SchemaTableName("default", "test1");
SchemaTableName test2Table = new SchemaTableName("default", "test2");
SchemaTableName test1Table = new SchemaTableName("DEFAULT", "test1");
SchemaTableName test2Table = new SchemaTableName("DEFAULT", "test2");
metadata.createTable(SESSION, new ConnectorTableMetadata(test1Table, ImmutableList.of()), false);

try {
Expand All @@ -89,7 +89,7 @@ public void tableAlreadyExists()
}
catch (PrestoException ex) {
assertEquals(ex.getErrorCode(), ALREADY_EXISTS.toErrorCode());
assertEquals(ex.getMessage(), "Table [default.test1] already exists");
assertEquals(ex.getMessage(), "Table [DEFAULT.test1] already exists");
}

ConnectorTableHandle test1TableHandle = metadata.getTableHandle(SESSION, test1Table);
Expand All @@ -101,7 +101,7 @@ public void tableAlreadyExists()
}
catch (PrestoException ex) {
assertEquals(ex.getErrorCode(), ALREADY_EXISTS.toErrorCode());
assertEquals(ex.getMessage(), "Table [default.test2] already exists");
assertEquals(ex.getMessage(), "Table [DEFAULT.test2] already exists");
}
}

Expand All @@ -110,15 +110,15 @@ public void testActiveTableIds()
{
assertNoTables();

SchemaTableName firstTableName = new SchemaTableName("default", "first_table");
SchemaTableName firstTableName = new SchemaTableName("DEFAULT", "first_table");
metadata.createTable(SESSION, new ConnectorTableMetadata(firstTableName, ImmutableList.of(), ImmutableMap.of()), false);

MemoryTableHandle firstTableHandle = (MemoryTableHandle) metadata.getTableHandle(SESSION, firstTableName);
long firstTableId = firstTableHandle.getId();

assertTrue(metadata.beginInsert(SESSION, firstTableHandle).getActiveTableIds().contains(firstTableId));

SchemaTableName secondTableName = new SchemaTableName("default", "second_table");
SchemaTableName secondTableName = new SchemaTableName("DEFAULT", "second_table");
metadata.createTable(SESSION, new ConnectorTableMetadata(secondTableName, ImmutableList.of(), ImmutableMap.of()), false);

MemoryTableHandle secondTableHandle = (MemoryTableHandle) metadata.getTableHandle(SESSION, secondTableName);
Expand All @@ -134,7 +134,7 @@ public void testReadTableBeforeCreationCompleted()
{
assertNoTables();

SchemaTableName tableName = new SchemaTableName("default", "temp_table");
SchemaTableName tableName = new SchemaTableName("DEFAULT", "temp_table");

ConnectorOutputTableHandle table = metadata.beginCreateTable(
SESSION,
Expand All @@ -150,9 +150,9 @@ public void testReadTableBeforeCreationCompleted()
@Test
public void testCreateSchema()
{
assertEquals(metadata.listSchemaNames(SESSION), ImmutableList.of("default"));
assertEquals(metadata.listSchemaNames(SESSION), ImmutableList.of("DEFAULT"));
metadata.createSchema(SESSION, "test", ImmutableMap.of());
assertEquals(metadata.listSchemaNames(SESSION), ImmutableList.of("default", "test"));
assertEquals(metadata.listSchemaNames(SESSION), ImmutableList.of("DEFAULT", "test"));
assertEquals(metadata.listTables(SESSION, Optional.of("test")), ImmutableList.of());

SchemaTableName tableName = new SchemaTableName("test", "first_table");
Expand All @@ -166,7 +166,7 @@ public void testCreateSchema()

assertEquals(metadata.listTables(SESSION, Optional.empty()), ImmutableList.of(tableName));
assertEquals(metadata.listTables(SESSION, Optional.of("test")), ImmutableList.of(tableName));
assertEquals(metadata.listTables(SESSION, Optional.of("default")), ImmutableList.of());
assertEquals(metadata.listTables(SESSION, Optional.of("DEFAULT")), ImmutableList.of());
}

@Test(expectedExceptions = PrestoException.class, expectedExceptionsMessageRegExp = "View already exists: test\\.test_view")
Expand Down Expand Up @@ -264,7 +264,7 @@ public void testViews()
@Test
public void testCreateTableAndViewInNotExistSchema()
{
assertEquals(metadata.listSchemaNames(SESSION), ImmutableList.of("default"));
assertEquals(metadata.listSchemaNames(SESSION), ImmutableList.of("DEFAULT"));

SchemaTableName table1 = new SchemaTableName("test1", "test_schema_table1");
try {
Expand Down Expand Up @@ -299,7 +299,7 @@ public void testCreateTableAndViewInNotExistSchema()
}
assertEquals(metadata.getTableHandle(SESSION, view3), null);

assertEquals(metadata.listSchemaNames(SESSION), ImmutableList.of("default"));
assertEquals(metadata.listSchemaNames(SESSION), ImmutableList.of("DEFAULT"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,39 +177,51 @@ public void testSelectColumnsSubset()
@Test
public void testCreateSchema()
{
assertQueryFails("DROP SCHEMA schema1", "line 1:1: Schema 'memory.schema1' does not exist");
assertQueryFails("DROP SCHEMA schema1", "line 1:1: Schema 'memory.SCHEMA1' does not exist");
assertQueryFails("DROP SCHEMA \"schema1\"", "line 1:1: Schema 'memory.schema1' does not exist");
assertUpdate("CREATE SCHEMA schema1");
assertQueryFails("CREATE SCHEMA schema1", "line 1:1: Schema 'memory.schema1' already exists");
assertQueryFails("CREATE SCHEMA SCHEMA1", "line 1:1: Schema 'memory.SCHEMA1' already exists");
assertUpdate("CREATE SCHEMA \"schema1\"");
assertQueryFails("CREATE SCHEMA \"schema1\"", "line 1:1: Schema 'memory.schema1' already exists");
assertUpdate("CREATE TABLE schema1.x(t int)");
assertQueryFails("DROP SCHEMA schema1", "Schema not empty: schema1");
assertUpdate("CREATE TABLE \"schema1\".\"x\"(t int)");
assertQueryFails("DROP SCHEMA schema1", "Schema not empty: SCHEMA1");
assertQueryFails("DROP SCHEMA \"schema1\"", "Schema not empty: schema1");
assertUpdate("DROP TABLE schema1.x");
assertUpdate("DROP TABLE \"schema1\".\"x\"");
assertUpdate("DROP SCHEMA schema1");
assertQueryFails("DROP SCHEMA schema1", "line 1:1: Schema 'memory.schema1' does not exist");
assertUpdate("DROP SCHEMA \"schema1\"");
assertQueryFails("DROP SCHEMA schema1", "line 1:1: Schema 'memory.SCHEMA1' does not exist");
assertQueryFails("DROP SCHEMA \"schema1\"", "line 1:1: Schema 'memory.schema1' does not exist");
assertUpdate("DROP SCHEMA IF EXISTS schema1");
assertUpdate("DROP SCHEMA IF EXISTS \"schema1\"");
}

@Test
public void testCreateTableInNonDefaultSchema()
{
assertUpdate("CREATE SCHEMA schema1");
assertUpdate("CREATE SCHEMA schema2");
assertUpdate("CREATE SCHEMA \"schema2\"");

assertQueryResult("SHOW SCHEMAS", "default", "information_schema", "schema1", "schema2");
assertUpdate("CREATE TABLE schema1.nation AS SELECT * FROM tpch.tiny.nation WHERE nationkey % 2 = 0", "SELECT count(*) FROM nation WHERE MOD(nationkey, 2) = 0");
assertUpdate("CREATE TABLE schema2.nation AS SELECT * FROM tpch.tiny.nation WHERE nationkey % 2 = 1", "SELECT count(*) FROM nation WHERE MOD(nationkey, 2) = 1");
assertQueryResult("SHOW SCHEMAS", "DEFAULT", "SCHEMA1", "information_schema", "schema2");
assertUpdate("CREATE TABLE scHema1.nation AS SELECT * FROM tpch.tiny.nation WHERE nationkey % 2 = 0", "SELECT count(*) FROM nation WHERE MOD(nationkey, 2) = 0");
assertUpdate("CREATE TABLE \"schema2\".nation AS SELECT * FROM tpch.tiny.nation WHERE nationkey % 2 = 1", "SELECT count(*) FROM nation WHERE MOD(nationkey, 2) = 1");

assertQueryResult("SELECT count(*) FROM schema1.nation", 13L);
assertQueryResult("SELECT count(*) FROM schema2.nation", 12L);
assertQueryResult("SELECT count(*) FROM schemA1.nation", 13L);
assertQueryResult("SELECT count(*) FROM \"schema2\".nation", 12L);
}

@Test
public void testCreateTableAndViewInNotExistSchema()
{
int tablesBeforeCreate = listMemoryTables().size();

assertQueryFails("CREATE TABLE schema3.test_table3 (x date)", "Schema schema3 not found");
assertQueryFails("CREATE VIEW schema4.test_view4 AS SELECT 123 x", "Schema schema4 not found");
assertQueryFails("CREATE OR REPLACE VIEW schema5.test_view5 AS SELECT 123 x", "Schema schema5 not found");
assertQueryFails("CREATE TABLE schema3.test_table3 (x date)", "Schema SCHEMA3 not found");
assertQueryFails("CREATE TABLE \"schema3\".test_table3 (x date)", "Schema schema3 not found");
assertQueryFails("CREATE VIEW \"schema4\".test_view4 AS SELECT 123 x", "Schema schema4 not found");
assertQueryFails("CREATE VIEW scheMa4.test_view4 AS SELECT 123 x", "Schema SCHEMA4 not found");
assertQueryFails("CREATE OR REPLACE VIEW \"schema5\".test_view5 AS SELECT 123 x", "Schema schema5 not found");
assertQueryFails("CREATE OR REPLACE VIEW scHema5.test_view5 AS SELECT 123 x", "Schema SCHEMA5 not found");

int tablesAfterCreate = listMemoryTables().size();
assertEquals(tablesBeforeCreate, tablesAfterCreate);
Expand All @@ -219,7 +231,7 @@ public void testCreateTableAndViewInNotExistSchema()
public void testRenameTable()
{
assertUpdate("CREATE TABLE test_table_to_be_renamed (a BIGINT)");
assertQueryFails("ALTER TABLE test_table_to_be_renamed RENAME TO memory.test_schema_not_exist.test_table_renamed", "Schema test_schema_not_exist not found");
assertQueryFails("ALTER TABLE test_table_to_be_renamed RENAME TO memory.test_schema_not_exist.test_table_renamed", "Schema TEST_SCHEMA_NOT_EXIST not found");
assertUpdate("ALTER TABLE test_table_to_be_renamed RENAME TO test_table_renamed");
assertQueryResult("SELECT count(*) FROM test_table_renamed", 0L);

Expand All @@ -236,18 +248,18 @@ public void testViews()
{
@Language("SQL") String query = "SELECT orderkey, orderstatus, totalprice / 2 half FROM orders";

assertUpdate("CREATE VIEW test_view AS SELECT 123 x");
assertUpdate("CREATE OR REPLACE VIEW test_view AS " + query);
assertUpdate("CREATE VIEW \"test_view\" AS SELECT 123 x");
assertUpdate("CREATE OR REPLACE VIEW \"test_view\" AS " + query);

assertQueryFails("CREATE TABLE test_view (x date)", "View \\[default.test_view] already exists");
assertQueryFails("CREATE VIEW test_view AS SELECT 123 x", "View already exists: default.test_view");
assertQueryFails("CREATE TABLE \"test_view\" (x date)", "View \\[DEFAULT.test_view] already exists");
assertQueryFails("CREATE VIEW \"test_view\" AS SELECT 123 x", "View already exists: DEFAULT.test_view");

assertQuery("SELECT * FROM test_view", query);
assertQuery("SELECT * FROM \"test_view\"", query);

assertTrue(computeActual("SHOW TABLES").getOnlyColumnAsSet().contains("test_view"));

assertUpdate("DROP VIEW test_view");
assertQueryFails("DROP VIEW test_view", "line 1:1: View 'memory.default.test_view' does not exist");
assertUpdate("DROP VIEW \"test_view\"");
assertQueryFails("DROP VIEW \"test_view\"", "line 1:1: View 'memory.default.test_view' does not exist");
}

@Test
Expand All @@ -256,7 +268,7 @@ public void testRenameView()
@Language("SQL") String query = "SELECT orderkey, orderstatus, totalprice / 2 half FROM orders";

assertUpdate("CREATE VIEW test_view_to_be_renamed AS " + query);
assertQueryFails("ALTER VIEW test_view_to_be_renamed RENAME TO memory.test_schema_not_exist.test_view_renamed", "Schema test_schema_not_exist not found");
assertQueryFails("ALTER VIEW test_view_to_be_renamed RENAME TO memory.test_schema_not_exist.test_view_renamed", "Schema TEST_SCHEMA_NOT_EXIST not found");
assertUpdate("ALTER VIEW test_view_to_be_renamed RENAME TO test_view_renamed");
assertQuery("SELECT * FROM test_view_renamed", query);

Expand All @@ -270,7 +282,7 @@ public void testRenameView()

private List<QualifiedObjectName> listMemoryTables()
{
return getQueryRunner().listTables(getSession(), "memory", "default");
return getQueryRunner().listTables(getSession(), "memory", "DEFAULT");
}

private void assertQueryResult(@Language("SQL") String sql, Object... expected)
Expand Down