diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java index add7434c..99f43267 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java @@ -174,20 +174,19 @@ public TableDescriptor getDescriptor(TableName tableName) throws IOException { @Override public void createTable(TableDescriptor tableDescriptor) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); -// ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableDescriptor.getTableName(), connectionConf); -// OHCreateTableExecutor executor = new OHCreateTableExecutor(tableClient); -// try { -// executor.createTable(tableDescriptor, null); -// } catch (IOException e) { -// if (e.getCause() instanceof ObTableTransportException -// && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { -// throw new TimeoutIOException(e.getCause()); -// } else { -// throw e; -// } -// } + OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableDescriptor.getTableName(), connectionConf); + OHCreateTableExecutor executor = new OHCreateTableExecutor(tableClient); + try { + executor.createTable(tableDescriptor, null); + } catch (IOException e) { + if (e.getCause() instanceof ObTableTransportException + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + throw new TimeoutIOException(e.getCause()); + } else { + throw e; + } + } } @Override @@ -207,20 +206,19 @@ public Future createTableAsync(TableDescriptor tableDescriptor, byte[][] b @Override public void deleteTable(TableName tableName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); -// ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); -// OHDeleteTableExecutor executor = new OHDeleteTableExecutor(tableClient); -// try { -// executor.deleteTable(tableName.getNameAsString()); -// } catch (IOException e) { -// if (e.getCause() instanceof ObTableTransportException -// && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { -// throw new TimeoutIOException(e.getCause()); -// } else { -// throw e; -// } -// } + OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); + OHDeleteTableExecutor executor = new OHDeleteTableExecutor(tableClient); + try { + executor.deleteTable(tableName.getNameAsString()); + } catch (IOException e) { + if (e.getCause() instanceof ObTableTransportException + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + throw new TimeoutIOException(e.getCause()); + } else { + throw e; + } + } } @Override @@ -250,20 +248,19 @@ public Future truncateTableAsync(TableName tableName, boolean b) throws IO @Override public void enableTable(TableName tableName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); -// ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); -// OHTableAccessControlExecutor executor = new OHTableAccessControlExecutor(tableClient, ObTableRpcMetaType.HTABLE_ENABLE_TABLE); -// try { -// executor.enableTable(tableName.getNameAsString()); -// } catch (IOException e) { -// if (e.getCause() instanceof ObTableTransportException -// && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { -// throw new TimeoutIOException(e.getCause()); -// } else { -// throw e; -// } -// } + OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); + OHTableAccessControlExecutor executor = new OHTableAccessControlExecutor(tableClient, ObTableRpcMetaType.HTABLE_ENABLE_TABLE); + try { + executor.enableTable(tableName.getNameAsString()); + } catch (IOException e) { + if (e.getCause() instanceof ObTableTransportException + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + throw new TimeoutIOException(e.getCause()); + } else { + throw e; + } + } } @Override @@ -315,14 +312,12 @@ public HTableDescriptor[] disableTables(Pattern pattern) throws IOException { @Override public boolean isTableEnabled(TableName tableName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// return isDisabled(tableName) == false; + return isDisabled(tableName) == false; } @Override public boolean isTableDisabled(TableName tableName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// return isDisabled(tableName) == true; + return isDisabled(tableName) == true; } private boolean isDisabled(TableName tableName) throws IOException { diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java index a56e8097..c7f87a04 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java @@ -53,7 +53,7 @@ public void createTable(TableDescriptor tableDescriptor, byte[][] splitKeys) thr final ObTableMetaRequest request = new ObTableMetaRequest(); request.setMetaType(getMetaType()); Map requestData = new HashMap<>(); - requestData.put("htable_name", tableDescriptor.getTableName().getName()); + requestData.put("htable_name", tableDescriptor.getTableName().getNameAsString()); Map> columnFamilies = new HashMap<>(); for (ColumnFamilyDescriptor columnDescriptor : tableDescriptor.getColumnFamilies()) { Map columnFamily = new HashMap<>(); diff --git a/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java b/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java index 748d21c8..f083a392 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java +++ b/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java @@ -35,6 +35,7 @@ import java.io.IOException; +import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.LinkedList; @@ -780,17 +781,17 @@ public void testCreateDeleteTable() throws Exception { assertTrue(admin.tableExists(tableName)); // TODO: show create table, need to be replace by getDescriptor java.sql.Connection conn = ObHTableTestUtil.getConnection(); - String selectSql = "show create table " + tableName.getNameAsString() + "$" + cf1; + String selectSql = "show create table " + tableName.getNameAsString() + "$" + Bytes.toString(cf1); System.out.println("execute sql: " + selectSql); java.sql.ResultSet resultSet = conn.createStatement().executeQuery(selectSql); ResultSetPrinter.print(resultSet); - selectSql = "show create table " + tableName.getNameAsString() + "$" + cf2; + selectSql = "show create table " + tableName.getNameAsString() + "$" + Bytes.toString(cf2); System.out.println("execute sql: " + selectSql); resultSet = conn.createStatement().executeQuery(selectSql); ResultSetPrinter.print(resultSet); - selectSql = "show create table " + tableName.getNameAsString() + "$" + cf3; + selectSql = "show create table " + tableName.getNameAsString() + "$" + Bytes.toString(cf3); System.out.println("execute sql: " + selectSql); resultSet = conn.createStatement().executeQuery(selectSql); ResultSetPrinter.print(resultSet); @@ -1033,4 +1034,198 @@ public void testConcurCreateDelPerf() throws Exception { duration = System.currentTimeMillis() - start; System.out.println("delete " + tableNums + " tables cost " + duration + " ms."); } + + @Test + public void testHTableDDLDefense() throws Exception { + TableName tableName = TableName.valueOf("testHTableDefense"); + byte[] cf1 = Bytes.toBytes("cf1"); + byte[] cf2 = Bytes.toBytes("cf2"); + Configuration conf = ObHTableTestUtil.newConfiguration(); + Connection connection = ConnectionFactory.createConnection(conf); + Admin admin = connection.getAdmin(); + + // 1. construct htable desc and column family desc + HColumnDescriptor hcd1 = new HColumnDescriptor(cf1); + hcd1.setMaxVersions(2); + hcd1.setTimeToLive(172800); + HColumnDescriptor hcd2 = new HColumnDescriptor(cf2); + hcd1.setMaxVersions(1); + hcd1.setTimeToLive(86400); + java.sql.Connection conn = ObHTableTestUtil.getConnection(); + + // 2. execute create table and check exists + try { + HTableDescriptor htd = new HTableDescriptor(tableName); + htd.addFamily(hcd1); + htd.addFamily(hcd2); + admin.createTable(htd); + assertTrue(admin.tableExists(tableName)); + + /// execute the following ddl stmt in created by admin table, should be prohibited + // 4. alter table add constraint + try { + String sql = "alter table testHTableDefense$cf1 ADD CONSTRAINT cons1 CHECK(T < 0)"; + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", e.getMessage()); + } + + // 5. alter table add index + try { + String sql = "alter table testHTableDefense$cf1 ADD INDEX idx_1(T)"; + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", e.getMessage()); + } + + // 5. alter table add fk + try { + String sql = "alter table testHTableDefense$cf1 MODIFY COLUMN V LONGTEXT"; + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", e.getMessage()); + } + + // 6. alter table modify column to lob + try { + String sql = "alter table testHTableDefense$cf1 ADD CONSTRAINT hbase_fk_1 FOREIGN KEY(K) REFERENCES testHTableDefense$cf2(K)"; + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", e.getMessage()); + } + + // 7. create trigger + try { + String sql = " CREATE TRIGGER hbase_trigger_1" + + " AFTER INSERT ON testHTableDefense$cf1 FOR EACH ROW" + + " BEGIN END"; + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", e.getMessage()); + } + + // 8. create view + try { + String sql = " CREATE VIEW hbase_view_1 as select * from testHTableDefense$cf1"; + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", e.getMessage()); + } + + // 9. alter view + try { + String sql = "ALTER VIEW hbase_view_1 as select * from testHTableDefense$cf1"; + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", e.getMessage()); + } + + // 10. create index + try { + String sql = " CREATE INDEX testHTableDefense$cf1_idx_T on testHTableDefense$cf1(T)"; + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", e.getMessage()); + } + + + // 11. explicit create table and specify created_by:admin, should be prohibited + try { + String sql = "CREATE TABLE testHTableDefense$cf3(a int primary key) kv_attributes ='{\"Hbase\": {\"CreatedBy\": \"Admin\"}}'"; + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", e.getMessage()); + } + + // 12. alter table to created_by:admin, should be prohibited + try { + String sql1 = "CREATE TABLE testHTableDefense$cf3(a int primary key)"; + System.out.println("execute sql: " + sql1); + conn.createStatement().execute(sql1); + String sql2 = "alter table testHTableDefense$cf3 kv_attributes ='{\"Hbase\": {\"CreatedBy\": \"Admin\"}}'"; + System.out.println("execute sql: " + sql2); + conn.createStatement().execute(sql2); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("alter table kv attributes to created by admin not supported", e.getMessage()); + // clean table + String sql3 = "drop table if exists testHTableDefense$cf3"; + System.out.println("execute sql: " + sql3); + conn.createStatement().execute(sql3); + } + + // 13. disable a htable did not created by admin is not suppported + try { + String sql1 = "CREATE TABLEGROUP IF NOT EXISTS testHTableDefense2"; + System.out.println("execute sql: " + sql1); + conn.createStatement().execute(sql1); + String sql2 = "CREATE TABLE IF NOT EXISTS testHTableDefense2$cf4(a int primary key) kv_attributes ='{\"Hbase\": {}}' TABLEGROUP=testHTableDefense2"; + System.out.println("execute sql: " + sql2); + conn.createStatement().execute(sql2); + admin.disableTable(TableName.valueOf("testHTableDefense2")); + fail(); + } catch (Exception e) { + Assert.assertEquals(-4007, ((ObTableException)e.getCause()).getErrorCode()); + + } + + // 14. delete a htable did not created by admin is not suppported + try { + String sql1 = "CREATE TABLEGROUP IF NOT EXISTS testHTableDefense2"; + System.out.println("execute sql: " + sql1); + conn.createStatement().execute(sql1); + String sql2 = "CREATE TABLE IF NOT EXISTS testHTableDefense2$cf5(a int primary key) kv_attributes ='{\"Hbase\": {}}' TABLEGROUP=testHTableDefense2"; + System.out.println("execute sql: " + sql2); + conn.createStatement().execute(sql2); + admin.deleteTable(TableName.valueOf("testHTableDefense2")); + fail(); + } catch (Exception e) { + Assert.assertEquals(-4007, ((ObTableException)e.getCause()).getErrorCode()); + } + + } catch (Exception e) { + e.printStackTrace(); + assertTrue(false); + } finally { + admin.disableTable(tableName); + admin.deleteTable(tableName); + String sql1 = "DROP TABLE IF EXISTS testHTableDefense2$cf4"; + System.out.println("execute sql: " + sql1); + conn.createStatement().execute(sql1); + String sql2 = "DROP TABLE IF EXISTS testHTableDefense2$cf5"; + System.out.println("execute sql: " + sql2); + conn.createStatement().execute(sql2); + String sql3 = "DROP TABLEGROUP IF EXISTS testHTableDefense2"; + System.out.println("execute sql: " + sql3); + conn.createStatement().execute(sql3); + } + } }