Author: gates Date: Tue Feb 10 21:41:19 2015 New Revision: 1658821 URL: http://svn.apache.org/r1658821 Log: HIVE-9578 Add support for getDatabases and alterDatabase calls [hbase-metastore branch]
Modified: hive/branches/hbase-metastore/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/hbase/TestHBaseStoreIntegration.java hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseReadWrite.java hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseStore.java hive/branches/hbase-metastore/metastore/src/test/org/apache/hadoop/hive/metastore/hbase/TestHBaseStore.java Modified: hive/branches/hbase-metastore/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/hbase/TestHBaseStoreIntegration.java URL: http://svn.apache.org/viewvc/hive/branches/hbase-metastore/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/hbase/TestHBaseStoreIntegration.java?rev=1658821&r1=1658820&r2=1658821&view=diff ============================================================================== --- hive/branches/hbase-metastore/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/hbase/TestHBaseStoreIntegration.java (original) +++ hive/branches/hbase-metastore/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/hbase/TestHBaseStoreIntegration.java Tue Feb 10 21:41:19 2015 @@ -20,7 +20,6 @@ package org.apache.hadoop.hive.metastore import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.client.HConnection; import org.apache.hadoop.hbase.client.HTableInterface; @@ -148,6 +147,44 @@ public class TestHBaseStoreIntegration { } @Test + public void getAllDbs() throws Exception { + String[] dbNames = new String[3]; + for (int i = 0; i < dbNames.length; i++) { + dbNames[i] = "db" + i; + Database db = new Database(dbNames[i], "no description", "file:///tmp", emptyParameters); + store.createDatabase(db); + } + + List<String> dbs = store.getAllDatabases(); + Assert.assertEquals(3, dbs.size()); + String[] namesFromStore = dbs.toArray(new String[3]); + Arrays.sort(namesFromStore); + Assert.assertArrayEquals(dbNames, namesFromStore); + } + + @Test + public void getDbsRegex() throws Exception { + String[] dbNames = new String[3]; + for (int i = 0; i < dbNames.length; i++) { + dbNames[i] = "db" + i; + Database db = new Database(dbNames[i], "no description", "file:///tmp", emptyParameters); + store.createDatabase(db); + } + + List<String> dbs = store.getDatabases("db1|db2"); + Assert.assertEquals(2, dbs.size()); + String[] namesFromStore = dbs.toArray(new String[2]); + Arrays.sort(namesFromStore); + Assert.assertArrayEquals(Arrays.copyOfRange(dbNames, 1, 3), namesFromStore); + + dbs = store.getDatabases("db*"); + Assert.assertEquals(3, dbs.size()); + namesFromStore = dbs.toArray(new String[3]); + Arrays.sort(namesFromStore); + Assert.assertArrayEquals(dbNames, namesFromStore); + } + + @Test public void createTable() throws Exception { int startTime = (int)(System.currentTimeMillis() / 1000); List<FieldSchema> cols = new ArrayList<FieldSchema>(); @@ -432,7 +469,7 @@ public class TestHBaseStoreIntegration { @Test public void createRole() throws Exception { - int now = (int)System.currentTimeMillis(); + int now = (int)System.currentTimeMillis()/1000; String roleName = "myrole"; store.addRole(roleName, "me"); @@ -444,14 +481,11 @@ public class TestHBaseStoreIntegration { @Test public void dropRole() throws Exception { - int now = (int)System.currentTimeMillis(); String roleName = "anotherrole"; store.addRole(roleName, "me"); Role r = store.getRole(roleName); Assert.assertEquals(roleName, r.getRoleName()); - Assert.assertEquals("me", r.getOwnerName()); - Assert.assertTrue(now <= r.getCreateTime()); store.removeRole(roleName); thrown.expect(NoSuchObjectException.class); Modified: hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseReadWrite.java URL: http://svn.apache.org/viewvc/hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseReadWrite.java?rev=1658821&r1=1658820&r2=1658821&view=diff ============================================================================== --- hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseReadWrite.java (original) +++ hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseReadWrite.java Tue Feb 10 21:41:19 2015 @@ -259,6 +259,29 @@ class HBaseReadWrite { } /** + * Get a list of databases. + * @param regex Regular expression to use in searching for database names. It is expected to + * be a Java regular expression. If it is null then all databases will be returned. + * @return list of databases matching the regular expression. + * @throws IOException + */ + List<Database> scanDatabases(String regex) throws IOException { + Filter filter = null; + if (regex != null) { + filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator(regex)); + } + Iterator<Result> iter = + scanWithFilter(DB_TABLE, null, CATALOG_CF, CATALOG_COL, filter); + List<Database> databases = new ArrayList<Database>(); + while (iter.hasNext()) { + DatabaseWritable db = new DatabaseWritable(); + HBaseUtils.deserialize(db, iter.next().getValue(CATALOG_CF, CATALOG_COL)); + databases.add(db.db); + } + return databases; + } + + /** * Store a database object * @param database database object to store * @throws IOException @@ -328,7 +351,7 @@ class HBaseReadWrite { : new ArrayList<Partition>(cached); } byte[] keyPrefix = HBaseUtils.buildKeyWithTrailingSeparator(dbName, tableName); - List<Partition> parts = scanOnPrefix(PART_TABLE, keyPrefix, CATALOG_CF, CATALOG_COL, -1); + List<Partition> parts = scanPartitions(keyPrefix, CATALOG_CF, CATALOG_COL, -1); partCache.put(dbName, tableName, parts, true); return maxPartitions < parts.size() ? parts.subList(0, maxPartitions) : parts; } @@ -352,7 +375,7 @@ class HBaseReadWrite { byte[] keyPrefix; if (partVals == null || partVals.size() == 0) { keyPrefix = HBaseUtils.buildKeyWithTrailingSeparator(dbName, tableName); - return scanOnPrefix(PART_TABLE, keyPrefix, CATALOG_CF, CATALOG_COL, maxPartitions); + return scanPartitions(keyPrefix, CATALOG_CF, CATALOG_COL, maxPartitions); } int firstNull = 0; for (; firstNull < partVals.size(); firstNull++) { @@ -360,7 +383,7 @@ class HBaseReadWrite { } if (firstNull == partVals.size()) { keyPrefix = buildPartitionKey(dbName, tableName, partVals); - return scanOnPrefix(PART_TABLE, keyPrefix, CATALOG_CF, CATALOG_COL, maxPartitions); + return scanPartitions(keyPrefix, CATALOG_CF, CATALOG_COL, maxPartitions); } keyPrefix = buildPartitionKey(dbName, tableName, partVals.subList(0, firstNull)); StringBuilder regex = new StringBuilder(); @@ -377,8 +400,8 @@ class HBaseReadWrite { Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator(regex.toString())); - List<Partition> parts = scanOnPrefixWithFilter(PART_TABLE, keyPrefix, CATALOG_CF, CATALOG_COL, - maxPartitions, filter); + List<Partition> parts = + scanPartitionsWithFilter(keyPrefix, CATALOG_CF, CATALOG_COL, maxPartitions, filter); partCache.put(dbName, tableName, parts, false); return parts; } @@ -835,24 +858,18 @@ class HBaseReadWrite { htab.delete(d); } - private List<Partition> scanOnPrefix(String table, byte[] keyPrefix, byte[] colFam, byte[] colName, - int maxResults) throws IOException { - return scanOnPrefixWithFilter(table, keyPrefix, colFam, colName, maxResults, null); + private List<Partition> scanPartitions(byte[] keyPrefix, byte[] colFam, byte[] colName, + int maxResults) throws IOException { + return scanPartitionsWithFilter(keyPrefix, colFam, colName, maxResults, null); } - private List<Partition> scanOnPrefixWithFilter(String table, byte[] keyPrefix, byte[] colFam, - byte[] colName, int maxResults, Filter filter) + private List<Partition> scanPartitionsWithFilter(byte[] keyPrefix, byte[] colFam, byte[] colName, + int maxResults, Filter filter) throws IOException { - HTableInterface htab = getHTable(table); - byte[] stop = Arrays.copyOf(keyPrefix, keyPrefix.length); - stop[stop.length - 1]++; - Scan s = new Scan(keyPrefix, stop); - s.addColumn(colFam, colName); - if (filter != null) s.setFilter(filter); - ResultScanner scanner = htab.getScanner(s); + Iterator<Result> iter = + scanWithFilter(PART_TABLE, keyPrefix, colFam, colName, filter); List<Partition> parts = new ArrayList<Partition>(); int numToFetch = maxResults < 0 ? Integer.MAX_VALUE : maxResults; - Iterator<Result> iter = scanner.iterator(); for (int i = 0; i < numToFetch && iter.hasNext(); i++) { PartitionWritable p = new PartitionWritable(); HBaseUtils.deserialize(p, iter.next().getValue(colFam, colName)); @@ -861,6 +878,23 @@ class HBaseReadWrite { return parts; } + private Iterator<Result> scanWithFilter(String table, byte[] keyPrefix, byte[] colFam, + byte[] colName, Filter filter) throws IOException { + HTableInterface htab = getHTable(table); + Scan s; + if (keyPrefix == null) { + s = new Scan(); + } else { + byte[] stop = Arrays.copyOf(keyPrefix, keyPrefix.length); + stop[stop.length - 1]++; + s = new Scan(keyPrefix, stop); + } + s.addColumn(colFam, colName); + if (filter != null) s.setFilter(filter); + ResultScanner scanner = htab.getScanner(s); + return scanner.iterator(); + } + private HTableInterface getHTable(String table) throws IOException { HTableInterface htab = tables.get(table); if (htab == null) { Modified: hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseStore.java URL: http://svn.apache.org/viewvc/hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseStore.java?rev=1658821&r1=1658820&r2=1658821&view=diff ============================================================================== --- hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseStore.java (original) +++ hive/branches/hbase-metastore/metastore/src/java/org/apache/hadoop/hive/metastore/hbase/HBaseStore.java Tue Feb 10 21:41:19 2015 @@ -148,17 +148,33 @@ public class HBaseStore implements RawSt @Override public boolean alterDatabase(String dbname, Database db) throws NoSuchObjectException, MetaException { - throw new UnsupportedOperationException(); + // ObjectStore fetches the old db before updating it, but I can't see the possible value of + // that since the caller will have needed to call getDatabase to have the db object. + try { + getHBase().putDb(db); + return true; + } catch (IOException e) { + LOG.error("Unable to alter database ", e); + throw new MetaException("Unable to read from or write to hbase " + e.getMessage()); + } } @Override public List<String> getDatabases(String pattern) throws MetaException { - throw new UnsupportedOperationException(); + try { + List<Database> dbs = getHBase().scanDatabases(likeToRegex(pattern)); + List<String> dbNames = new ArrayList<String>(dbs.size()); + for (Database db : dbs) dbNames.add(db.getName()); + return dbNames; + } catch (IOException e) { + LOG.error("Unable to get databases ", e); + throw new MetaException("Unable to get databases, " + e.getMessage()); + } } @Override public List<String> getAllDatabases() throws MetaException { - throw new UnsupportedOperationException(); + return getDatabases(null); } @Override @@ -964,4 +980,14 @@ public class HBaseStore implements RawSt } return vals; } + + private String likeToRegex(String like) { + if (like == null) return null; + // Convert Hive's strange like syntax to Java regex. Per + // https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-Show + // the supported syntax is that * means Java .* and | means 'or' + // This implementation leaves other regular expression syntax alone, which means people can + // use it, even though it wouldn't work on RDBMS backed metastores. + return like.replace("*", ".*"); + } } Modified: hive/branches/hbase-metastore/metastore/src/test/org/apache/hadoop/hive/metastore/hbase/TestHBaseStore.java URL: http://svn.apache.org/viewvc/hive/branches/hbase-metastore/metastore/src/test/org/apache/hadoop/hive/metastore/hbase/TestHBaseStore.java?rev=1658821&r1=1658820&r2=1658821&view=diff ============================================================================== --- hive/branches/hbase-metastore/metastore/src/test/org/apache/hadoop/hive/metastore/hbase/TestHBaseStore.java (original) +++ hive/branches/hbase-metastore/metastore/src/test/org/apache/hadoop/hive/metastore/hbase/TestHBaseStore.java Tue Feb 10 21:41:19 2015 @@ -105,6 +105,20 @@ public class TestHBaseStore { } @Test + public void alterDb() throws Exception { + String dbname = "mydb"; + Database db = new Database(dbname, "no description", "file:///tmp", emptyParameters); + store.createDatabase(db); + db.setDescription("a description"); + store.alterDatabase(dbname, db); + + Database d = store.getDatabase(dbname); + Assert.assertEquals(dbname, d.getName()); + Assert.assertEquals("a description", d.getDescription()); + Assert.assertEquals("file:///tmp", d.getLocationUri()); + } + + @Test public void dropDb() throws Exception { String dbname = "anotherdb"; Database db = new Database(dbname, "no description", "file:///tmp", emptyParameters); @@ -352,7 +366,7 @@ public class TestHBaseStore { @Test public void createRole() throws Exception { - int now = (int)System.currentTimeMillis(); + int now = (int)System.currentTimeMillis()/1000; String roleName = "myrole"; store.addRole(roleName, "me");