blob: 66d4777b9eb3dfb1f0a31a13302030ed3b1978e7 [file] [log] [blame]
/*
* 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
*
* 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.phoenix.end2end;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import org.apache.hadoop.hbase.DoNotRetryIOException;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.RegionLocator;
import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.query.BaseTest;
import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.ReadOnlyProps;
import org.apache.phoenix.util.SchemaUtil;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import com.google.common.collect.Maps;
@Category(NeedsOwnMiniClusterTest.class)
public class SystemCatalogIT extends BaseTest {
private HBaseTestingUtility testUtil = null;
@BeforeClass
public static synchronized void doSetup() throws Exception {
Map<String, String> serverProps = Maps.newHashMapWithExpectedSize(1);
serverProps.put(QueryServices.SYSTEM_CATALOG_SPLITTABLE, "false");
serverProps.put(QueryServices.ALLOW_SPLITTABLE_SYSTEM_CATALOG_ROLLBACK, "true");
Map<String, String> clientProps = Collections.emptyMap();
setUpTestDriver(new ReadOnlyProps(serverProps.entrySet().iterator()),
new ReadOnlyProps(clientProps.entrySet().iterator()));
}
/**
* Make sure that SYSTEM.CATALOG cannot be split if QueryServices.SYSTEM_CATALOG_SPLITTABLE is false
*/
@Test
public void testSystemTableSplit() throws Exception {
testUtil = getUtility();
for (int i=0; i<10; i++) {
createTable("schema"+i+".table_"+i);
}
TableName systemCatalog = TableName.valueOf("SYSTEM.CATALOG");
RegionLocator rl = testUtil.getConnection().getRegionLocator(systemCatalog);
assertEquals(rl.getAllRegionLocations().size(), 1);
try {
// now attempt to split SYSTEM.CATALOG
testUtil.getAdmin().split(systemCatalog);
// make sure the split finishes (there's no synchronous splitting before HBase 2.x)
testUtil.getAdmin().disableTable(systemCatalog);
testUtil.getAdmin().enableTable(systemCatalog);
} catch (DoNotRetryIOException e) {
// table is not splittable
assert (e.getMessage().contains("NOT splittable"));
}
// test again... Must still be exactly one region.
rl = testUtil.getConnection().getRegionLocator(systemCatalog);
assertEquals(1, rl.getAllRegionLocations().size());
}
private void createTable(String tableName) throws Exception {
try (Connection conn = DriverManager.getConnection(getJdbcUrl());
Statement stmt = conn.createStatement();) {
stmt.execute("DROP TABLE IF EXISTS " + tableName);
stmt.execute("CREATE TABLE " + tableName
+ " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR CONSTRAINT PK " +
"PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT=true");
try (Connection tenant1Conn = getTenantConnection("tenant1")) {
String view1DDL = "CREATE VIEW " + tableName + "_view AS SELECT * FROM " + tableName;
tenant1Conn.createStatement().execute(view1DDL);
}
conn.commit();
}
}
private String getJdbcUrl() {
return "jdbc:phoenix:localhost:" + getUtility().getZkCluster().getClientPort() + ":/hbase";
}
private Connection getTenantConnection(String tenantId) throws SQLException {
Properties tenantProps = new Properties();
tenantProps.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
return DriverManager.getConnection(getJdbcUrl(), tenantProps);
}
/**
* Ensure that we cannot add a column to a base table if QueryServices.BLOCK_METADATA_CHANGES_REQUIRE_PROPAGATION
* is true
*/
@Test
public void testAddingColumnFails() throws Exception {
try (Connection conn = DriverManager.getConnection(getJdbcUrl())) {
String fullTableName = SchemaUtil.getTableName(generateUniqueName(), generateUniqueName());
String fullViewName = SchemaUtil.getTableName(generateUniqueName(), generateUniqueName());
String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, v1 INTEGER " +
"CONSTRAINT pk PRIMARY KEY (k1))";
conn.createStatement().execute(ddl);
ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullTableName;
conn.createStatement().execute(ddl);
try {
ddl = "ALTER TABLE " + fullTableName + " ADD v2 INTEGER";
conn.createStatement().execute(ddl);
fail();
}
catch (SQLException e) {
assertEquals(SQLExceptionCode.CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
}
}
}
}