diff --git a/fe/fe-core/src/main/java/com/starrocks/catalog/Database.java b/fe/fe-core/src/main/java/com/starrocks/catalog/Database.java index 0d2505af3e0d8..3fc44cd78f499 100644 --- a/fe/fe-core/src/main/java/com/starrocks/catalog/Database.java +++ b/fe/fe-core/src/main/java/com/starrocks/catalog/Database.java @@ -300,6 +300,17 @@ public long getId() { return id; } + /** + * Get the unique id of database in string format, since we already ensure + * the uniqueness of id for internal database, we just convert it to string + * and return, for external database it's up to the implementation of connector. + * + * @return unique id of database in string format + */ + public String getUUID() { + return Long.toString(id); + } + public String getOriginName() { return fullQualifiedName; } diff --git a/fe/fe-core/src/main/java/com/starrocks/catalog/Table.java b/fe/fe-core/src/main/java/com/starrocks/catalog/Table.java index b8c272fb77e8e..b99aa0e38ce9f 100644 --- a/fe/fe-core/src/main/java/com/starrocks/catalog/Table.java +++ b/fe/fe-core/src/main/java/com/starrocks/catalog/Table.java @@ -179,6 +179,17 @@ public long getId() { return id; } + /** + * Get the unique id of table in string format, since we already ensure + * the uniqueness of id for internal table, we just convert it to string + * and return, for external table it's up to the implementation of connector. + * + * @return unique id of table in string format + */ + public String getUUID() { + return Long.toString(id); + } + public void setId(long id) { this.id = id; } diff --git a/fe/fe-core/src/main/java/com/starrocks/privilege/DbPEntryObject.java b/fe/fe-core/src/main/java/com/starrocks/privilege/DbPEntryObject.java index 92951ac3d0f91..ac51e4f9c4c64 100644 --- a/fe/fe-core/src/main/java/com/starrocks/privilege/DbPEntryObject.java +++ b/fe/fe-core/src/main/java/com/starrocks/privilege/DbPEntryObject.java @@ -23,13 +23,17 @@ import java.util.Objects; public class DbPEntryObject implements PEntryObject { - public static final long ALL_DATABASE_ID = -2; // -2 represent all + public static final String ALL_DATABASES_UUID = "ALL_DATABASES_UUID"; // represent all databases @SerializedName(value = "i") - private long id; + private String uuid; - public long getId() { - return id; + public String getUUID() { + return uuid; + } + + protected DbPEntryObject(String uuid) { + this.uuid = uuid; } public static DbPEntryObject generate(GlobalStateMgr mgr, List tokens) throws PrivilegeException { @@ -38,18 +42,23 @@ public static DbPEntryObject generate(GlobalStateMgr mgr, List tokens) t } if (tokens.get(0).equals("*")) { - return new DbPEntryObject(ALL_DATABASE_ID); + return new DbPEntryObject(ALL_DATABASES_UUID); } Database database = mgr.getDb(tokens.get(0)); if (database == null) { throw new PrivObjNotFoundException("cannot find db: " + tokens.get(0)); } - return new DbPEntryObject(database.getId()); + return new DbPEntryObject(database.getUUID()); } - protected DbPEntryObject(long dbId) { - id = dbId; + public static DbPEntryObject generate( + List allTypes, String restrictType, String restrictName) throws PrivilegeException { + // only support ON ALL DATABASE + if (allTypes.size() != 1 || restrictType != null || restrictName != null) { + throw new PrivilegeException("invalid ALL statement for databases! only support ON ALL DATABASES"); + } + return new DbPEntryObject(ALL_DATABASES_UUID); } /** @@ -65,25 +74,26 @@ public boolean match(Object obj) { return false; } DbPEntryObject other = (DbPEntryObject) obj; - if (other.id == ALL_DATABASE_ID) { + if (Objects.equals(other.uuid, ALL_DATABASES_UUID)) { return true; } - return other.id == id; + return Objects.equals(other.uuid, uuid); } @Override public boolean isFuzzyMatching() { - return ALL_DATABASE_ID == id; + return ALL_DATABASES_UUID.equals(uuid); } @Override public boolean validate(GlobalStateMgr globalStateMgr) { - return globalStateMgr.getDbIncludeRecycleBin(this.id) != null; + // TODO(yiming): change validation method for external catalog + return globalStateMgr.getDbIncludeRecycleBin(Long.parseLong(this.uuid)) != null; } @Override public PEntryObject clone() { - return new DbPEntryObject(id); + return new DbPEntryObject(uuid); } @Override @@ -92,7 +102,17 @@ public int compareTo(PEntryObject obj) { throw new ClassCastException("cannot cast " + obj.getClass().toString() + " to " + this.getClass()); } DbPEntryObject o = (DbPEntryObject) obj; - return Long.compare(this.id, o.id); + // Always put the fuzzy matching object at the front of the privilege entry list + // when sorting in ascendant order. + if (Objects.equals(this.uuid, o.uuid)) { + return 0; + } else if (Objects.equals(this.uuid, ALL_DATABASES_UUID)) { + return -1; + } else if (Objects.equals(o.uuid, ALL_DATABASES_UUID)) { + return 1; + } else { + return this.uuid.compareTo(o.uuid); + } } @Override @@ -104,11 +124,11 @@ public boolean equals(Object o) { return false; } DbPEntryObject that = (DbPEntryObject) o; - return id == that.id; + return Objects.equals(uuid, that.uuid); } @Override public int hashCode() { - return Objects.hash(id); + return Objects.hash(uuid); } } diff --git a/fe/fe-core/src/main/java/com/starrocks/privilege/MaterializedViewPEntryObject.java b/fe/fe-core/src/main/java/com/starrocks/privilege/MaterializedViewPEntryObject.java index df19328fed419..d5451d67cb4fb 100644 --- a/fe/fe-core/src/main/java/com/starrocks/privilege/MaterializedViewPEntryObject.java +++ b/fe/fe-core/src/main/java/com/starrocks/privilege/MaterializedViewPEntryObject.java @@ -22,8 +22,8 @@ public class MaterializedViewPEntryObject extends TablePEntryObject { - protected MaterializedViewPEntryObject(long databaseId, long tableId) { - super(databaseId, tableId); + protected MaterializedViewPEntryObject(String dbUUID, String tblUUID) { + super(dbUUID, tblUUID); } public static MaterializedViewPEntryObject generate(GlobalStateMgr mgr, List tokens) @@ -31,31 +31,31 @@ public static MaterializedViewPEntryObject generate(GlobalStateMgr mgr, List object = Collections.singletonList(new TablePEntryObject( - SystemId.INFORMATION_SCHEMA_DB_ID, TablePEntryObject.ALL_TABLES_ID)); - rolePrivilegeCollection.grant(ObjectType.TABLE, Collections.singletonList(PrivilegeType.SELECT), object, false); + Long.toString(SystemId.INFORMATION_SCHEMA_DB_ID), TablePEntryObject.ALL_TABLES_UUID)); + rolePrivilegeCollection.grant(ObjectType.TABLE, Collections.singletonList(PrivilegeType.SELECT), object, + false); // 6. builtin user root UserPrivilegeCollection rootCollection = new UserPrivilegeCollection(); diff --git a/fe/fe-core/src/main/java/com/starrocks/privilege/TablePEntryObject.java b/fe/fe-core/src/main/java/com/starrocks/privilege/TablePEntryObject.java index 306d472ac73c7..30fdf7370b739 100644 --- a/fe/fe-core/src/main/java/com/starrocks/privilege/TablePEntryObject.java +++ b/fe/fe-core/src/main/java/com/starrocks/privilege/TablePEntryObject.java @@ -24,56 +24,56 @@ import java.util.Objects; public class TablePEntryObject implements PEntryObject { - public static final long ALL_DATABASE_ID = -2; // -2 represent all databases - public static final long ALL_TABLES_ID = -3; // -3 represent all tables + public static final String ALL_DATABASE_UUID = "ALL_DATABASES_UUID"; // represent all databases + public static final String ALL_TABLES_UUID = "ALL_TABLES_UUID"; // represent all tables @SerializedName(value = "d") - protected long databaseId; + protected String databaseUUID; @SerializedName(value = "t") - protected long tableId; + protected String tableUUID; - public long getDatabaseId() { - return databaseId; + public String getDatabaseUUID() { + return databaseUUID; } - public long getTableId() { - return tableId; + public String getTableUUID() { + return tableUUID; } public static TablePEntryObject generate(GlobalStateMgr mgr, List tokens) throws PrivilegeException { if (tokens.size() != 2) { throw new PrivilegeException("invalid object tokens, should have two: " + tokens); } - long dbId; - long tableId; + String dbUUID; + String tblUUID; if (tokens.get(0).equals("*")) { - dbId = ALL_DATABASE_ID; - tableId = ALL_TABLES_ID; + dbUUID = ALL_DATABASE_UUID; + tblUUID = ALL_TABLES_UUID; } else { Database database = mgr.getDb(tokens.get(0)); if (database == null) { throw new PrivObjNotFoundException("cannot find db: " + tokens.get(0)); } - dbId = database.getId(); + dbUUID = database.getUUID(); if (tokens.get(1).equals("*")) { - tableId = ALL_TABLES_ID; + tblUUID = ALL_TABLES_UUID; } else { Table table = database.getTable(tokens.get(1)); if (table == null) { throw new PrivObjNotFoundException("cannot find table " + tokens.get(1) + " in db " + tokens.get(0)); } - tableId = table.getId(); + tblUUID = table.getUUID(); } } - return new TablePEntryObject(dbId, tableId); + return new TablePEntryObject(dbUUID, tblUUID); } - protected TablePEntryObject(long databaseId, long tableId) { - this.tableId = tableId; - this.databaseId = databaseId; + protected TablePEntryObject(String databaseUUID, String tableUUID) { + this.tableUUID = tableUUID; + this.databaseUUID = databaseUUID; } /** @@ -89,28 +89,29 @@ public boolean match(Object obj) { return false; } TablePEntryObject other = (TablePEntryObject) obj; - if (other.databaseId == ALL_DATABASE_ID) { + if (Objects.equals(other.databaseUUID, ALL_DATABASE_UUID)) { return true; } - if (other.tableId == ALL_TABLES_ID) { - return databaseId == other.databaseId; + if (Objects.equals(other.tableUUID, ALL_TABLES_UUID)) { + return Objects.equals(databaseUUID, other.databaseUUID); } - return other.databaseId == databaseId && other.tableId == tableId; + return Objects.equals(other.databaseUUID, databaseUUID) && Objects.equals(other.tableUUID, tableUUID); } @Override public boolean isFuzzyMatching() { - return databaseId == ALL_DATABASE_ID || tableId == ALL_TABLES_ID; + return Objects.equals(databaseUUID, ALL_DATABASE_UUID) || Objects.equals(tableUUID, ALL_TABLES_UUID); } @Override public boolean validate(GlobalStateMgr globalStateMgr) { - Database db = globalStateMgr.getDbIncludeRecycleBin(this.databaseId); + // TODO(yiming): change validation method for external catalog + Database db = globalStateMgr.getDbIncludeRecycleBin(Long.parseLong(this.databaseUUID)); if (db == null) { return false; } - return globalStateMgr.getTableIncludeRecycleBin(db, this.tableId) != null; + return globalStateMgr.getTableIncludeRecycleBin(db, Long.parseLong(this.tableUUID)) != null; } @Override @@ -118,14 +119,26 @@ public int compareTo(PEntryObject obj) { if (!(obj instanceof TablePEntryObject)) { throw new ClassCastException("cannot cast " + obj.getClass().toString() + " to " + this.getClass()); } - TablePEntryObject o = (TablePEntryObject) obj; - if (this.databaseId > o.databaseId) { - return 1; - } else if (this.databaseId < o.databaseId) { + TablePEntryObject o = (TablePEntryObject) obj; + // Always put the fuzzy matching object at the front of the privilege entry list + // when sorting in ascendant order. + if (Objects.equals(this.databaseUUID, o.databaseUUID)) { + if (Objects.equals(this.tableUUID, o.tableUUID)) { + return 0; + } else if (Objects.equals(this.tableUUID, ALL_TABLES_UUID)) { + return -1; + } else if (Objects.equals(o.tableUUID, ALL_TABLES_UUID)) { + return 1; + } else { + return this.tableUUID.compareTo(o.tableUUID); + } + } else if (Objects.equals(this.databaseUUID, ALL_DATABASE_UUID)) { return -1; + } else if (Objects.equals(o.databaseUUID, ALL_DATABASE_UUID)) { + return 1; } else { - return Long.compare(this.tableId, o.tableId); + return this.databaseUUID.compareTo(o.databaseUUID); } } @@ -138,16 +151,16 @@ public boolean equals(Object o) { return false; } TablePEntryObject that = (TablePEntryObject) o; - return databaseId == that.databaseId && tableId == that.tableId; + return Objects.equals(databaseUUID, that.databaseUUID) && Objects.equals(tableUUID, that.tableUUID); } @Override public int hashCode() { - return Objects.hash(databaseId, tableId); + return Objects.hash(databaseUUID, tableUUID); } @Override public PEntryObject clone() { - return new TablePEntryObject(databaseId, tableId); + return new TablePEntryObject(databaseUUID, tableUUID); } } diff --git a/fe/fe-core/src/main/java/com/starrocks/privilege/ViewPEntryObject.java b/fe/fe-core/src/main/java/com/starrocks/privilege/ViewPEntryObject.java index 834ce57f4d6e0..188d343271b91 100644 --- a/fe/fe-core/src/main/java/com/starrocks/privilege/ViewPEntryObject.java +++ b/fe/fe-core/src/main/java/com/starrocks/privilege/ViewPEntryObject.java @@ -25,38 +25,38 @@ * View is a subclass of table, only the table type is different */ public class ViewPEntryObject extends TablePEntryObject { - protected ViewPEntryObject(long databaseId, long tableId) { - super(databaseId, tableId); + protected ViewPEntryObject(String dbUUID, String tblUUID) { + super(dbUUID, tblUUID); } public static ViewPEntryObject generate(GlobalStateMgr mgr, List tokens) throws PrivilegeException { if (tokens.size() != 2) { throw new PrivilegeException("invalid object tokens, should have two: " + tokens); } - long dbId; - long tableId; + String dbUUID; + String tblUUID; if (tokens.get(0).equals("*")) { - dbId = ALL_DATABASE_ID; - tableId = ALL_TABLES_ID; + dbUUID = ALL_DATABASE_UUID; + tblUUID = ALL_TABLES_UUID; } else { Database database = mgr.getDb(tokens.get(0)); if (database == null) { throw new PrivObjNotFoundException("cannot find db: " + tokens.get(0)); } - dbId = database.getId(); + dbUUID = database.getUUID(); if (tokens.get(1).equals("*")) { - tableId = ALL_TABLES_ID; + tblUUID = ALL_TABLES_UUID; } else { Table table = database.getTable(tokens.get(1)); if (table == null || !table.getType().equals(Table.TableType.VIEW)) { throw new PrivObjNotFoundException("cannot find view " + tokens.get(1) + " in db " + tokens.get(0)); } - tableId = table.getId(); + tblUUID = table.getUUID(); } } - return new ViewPEntryObject(dbId, tableId); + return new ViewPEntryObject(dbUUID, tblUUID); } } diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AstToStringBuilder.java b/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AstToStringBuilder.java index 6fa522b21e307..b12b6fd928f6f 100644 --- a/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AstToStringBuilder.java +++ b/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AstToStringBuilder.java @@ -109,6 +109,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -331,20 +332,23 @@ public String visitGrantRevokePrivilegeStatement(BaseGrantRevokePrivilegeStmt st case VIEW: case MATERIALIZED_VIEW: { TablePEntryObject tablePEntryObject = (TablePEntryObject) stmt.getObjectList().get(0); - if (tablePEntryObject.getDatabaseId() == TablePEntryObject.ALL_DATABASE_ID) { + if (Objects.equals(tablePEntryObject.getDatabaseUUID(), TablePEntryObject.ALL_DATABASE_UUID)) { sb.append("ALL ").append(plural).append(" IN ALL DATABASES"); } else { - Database database = GlobalStateMgr.getCurrentState().getDb(tablePEntryObject.getDatabaseId()); - if (tablePEntryObject.getTableId() == TablePEntryObject.ALL_TABLES_ID) { + // TODO(yiming): change it for external catalog + Database database = GlobalStateMgr.getCurrentState() + .getDb(Long.parseLong(tablePEntryObject.getDatabaseUUID())); + if (Objects.equals(tablePEntryObject.getTableUUID(), TablePEntryObject.ALL_TABLES_UUID)) { sb.append("ALL TABLES "); sb.append("IN DATABASE ").append(database.getFullName()); } else { sb.append(stmt.getObjectType().name()).append(" "); - List objectString = new ArrayList<>(); for (PEntryObject pEntryObject : stmt.getObjectList()) { + TablePEntryObject tp = (TablePEntryObject) pEntryObject; - Table table = database.getTable(tp.getTableId()); + // TODO(yiming): change it for external catalog + Table table = database.getTable(Long.parseLong(tp.getTableUUID())); objectString.add(database.getFullName() + "." + table.getName()); } sb.append(Joiner.on(", ").join(objectString)); @@ -354,11 +358,13 @@ public String visitGrantRevokePrivilegeStatement(BaseGrantRevokePrivilegeStmt st } case DATABASE: { DbPEntryObject dbPEntryObject = (DbPEntryObject) stmt.getObjectList().get(0); - if (dbPEntryObject.getId() == DbPEntryObject.ALL_DATABASE_ID) { + if (Objects.equals(dbPEntryObject.getUUID(), DbPEntryObject.ALL_DATABASES_UUID)) { sb.append("ALL DATABASES"); } else { sb.append(stmt.getObjectType().name()).append(" "); - Database database = GlobalStateMgr.getCurrentState().getDb(dbPEntryObject.getId()); + // TODO(yiming): change it for external catalog + Database database = + GlobalStateMgr.getCurrentState().getDb(Long.parseLong(dbPEntryObject.getUUID())); sb.append(database.getFullName()); } break; diff --git a/fe/fe-core/src/test/java/com/starrocks/privilege/PrivilegeCollectionTest.java b/fe/fe-core/src/test/java/com/starrocks/privilege/PrivilegeCollectionTest.java index 8fac58a76efee..8e328b94604ef 100644 --- a/fe/fe-core/src/test/java/com/starrocks/privilege/PrivilegeCollectionTest.java +++ b/fe/fe-core/src/test/java/com/starrocks/privilege/PrivilegeCollectionTest.java @@ -29,7 +29,7 @@ public void testBasic() throws Exception { PrivilegeType select = PrivilegeType.SELECT; PrivilegeType insert = PrivilegeType.INSERT; PrivilegeType delete = PrivilegeType.DELETE; - TablePEntryObject table1 = new TablePEntryObject(1, 2); + TablePEntryObject table1 = new TablePEntryObject("1", "2"); ObjectType system = ObjectType.SYSTEM; Assert.assertFalse(collection.check(table, insert, table1)); @@ -90,7 +90,7 @@ public void testGrantOptionComplicated() throws Exception { PrivilegeType select = PrivilegeType.SELECT; PrivilegeType insert = PrivilegeType.INSERT; PrivilegeType delete = PrivilegeType.DELETE; - TablePEntryObject table1 = new TablePEntryObject(1, 2); + TablePEntryObject table1 = new TablePEntryObject("1", "2"); // grant select on table1 with grant option collection.grant(table, Arrays.asList(select), Arrays.asList(table1), true); @@ -145,10 +145,10 @@ public void testAll() throws Exception { ObjectType table = ObjectType.TABLE; PrivilegeType select = PrivilegeType.SELECT; PrivilegeType insert = PrivilegeType.INSERT; - TablePEntryObject table1 = new TablePEntryObject(1, 2); - TablePEntryObject allTablesInDb = new TablePEntryObject(1, TablePEntryObject.ALL_TABLES_ID); + TablePEntryObject table1 = new TablePEntryObject("1", "2"); + TablePEntryObject allTablesInDb = new TablePEntryObject("1", TablePEntryObject.ALL_TABLES_UUID); TablePEntryObject allTablesInALLDb = new TablePEntryObject( - TablePEntryObject.ALL_DATABASE_ID, TablePEntryObject.ALL_TABLES_ID); + TablePEntryObject.ALL_DATABASE_UUID, TablePEntryObject.ALL_TABLES_UUID); // grant select,insert on db1.table1 collection.grant(table, Arrays.asList(select, insert), Arrays.asList(table1), false); @@ -192,10 +192,10 @@ public void testMergeCollection() throws Exception { PrivilegeType select = PrivilegeType.SELECT; PrivilegeType insert = PrivilegeType.INSERT; - TablePEntryObject table1 = new TablePEntryObject(111, 222); + TablePEntryObject table1 = new TablePEntryObject("111", "222"); ObjectType db = ObjectType.DATABASE; PrivilegeType drop = PrivilegeType.DROP; - DbPEntryObject db1 = new DbPEntryObject(333); + DbPEntryObject db1 = new DbPEntryObject("333"); PrivilegeCollection collection = new PrivilegeCollection(); PrivilegeCollection selectTable = new PrivilegeCollection(); @@ -245,7 +245,7 @@ public void testPEntryCopyConstructor() throws Exception { PrivilegeType select = PrivilegeType.SELECT; PrivilegeType insert = PrivilegeType.INSERT; PrivilegeType delete = PrivilegeType.DELETE; - TablePEntryObject table1 = new TablePEntryObject(111, 222); + TablePEntryObject table1 = new TablePEntryObject("111", "222"); PrivilegeCollection.PrivilegeEntry entry = new PrivilegeCollection.PrivilegeEntry( new ActionSet(Arrays.asList(select, insert)), table1, diff --git a/fe/fe-core/src/test/java/com/starrocks/privilege/PrivilegeManagerTest.java b/fe/fe-core/src/test/java/com/starrocks/privilege/PrivilegeManagerTest.java index c0c096cd9bcd7..7e6e8ab92f5f2 100644 --- a/fe/fe-core/src/test/java/com/starrocks/privilege/PrivilegeManagerTest.java +++ b/fe/fe-core/src/test/java/com/starrocks/privilege/PrivilegeManagerTest.java @@ -559,16 +559,16 @@ public void testRemoveInvalidateObject() throws Exception { manager.grant(grantDbStmt); List objects = Arrays.asList(goodTableObject); // 3. add invalidate entry: select on invalidatedb.table - objects = Arrays.asList(new TablePEntryObject(-1, goodTableObject.tableId)); + objects = Arrays.asList(new TablePEntryObject("-1", goodTableObject.tableUUID)); manager.grantToUser(grantTableStmt.getObjectType(), grantTableStmt.getPrivilegeTypes(), objects, false, testUser); // 4. add invalidate entry: select on db.invalidatetable - objects = Arrays.asList(new TablePEntryObject(goodTableObject.databaseId, -1)); + objects = Arrays.asList(new TablePEntryObject(goodTableObject.databaseUUID, "-1")); manager.grantToUser(grantTableStmt.getObjectType(), grantTableStmt.getPrivilegeTypes(), objects, false, testUser); // 5. add invalidate entry: create_table, drop on invalidatedb - objects = Arrays.asList(new DbPEntryObject(-1)); + objects = Arrays.asList(new DbPEntryObject("-1")); manager.grantToUser(grantDbStmt.getObjectType(), grantDbStmt.getPrivilegeTypes(), objects, false, testUser); // 6. add valid entry: ALL databases - objects = Arrays.asList(new DbPEntryObject(DbPEntryObject.ALL_DATABASE_ID)); + objects = Arrays.asList(new DbPEntryObject(DbPEntryObject.ALL_DATABASES_UUID)); manager.grantToUser(grantDbStmt.getObjectType(), grantDbStmt.getPrivilegeTypes(), objects, false, testUser); // 7. add valid user sql = "grant impersonate on USER root to test_user";