-
Notifications
You must be signed in to change notification settings - Fork 38
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
Unify admin behavior #856
Unify admin behavior #856
Conversation
e22d2fd
to
4c46db7
Compare
@@ -15,6 +15,7 @@ public interface Admin { | |||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documented the unified admin behaviors.
@@ -14,6 +14,8 @@ public interface DistributedTransactionAdmin extends Admin { | |||
* Creates coordinator namespace and tables. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto. Documented the unified admin behaviors.
import java.util.Set; | ||
import javax.annotation.Nullable; | ||
|
||
public class CheckedDistributedStorageAdmin implements DistributedStorageAdmin { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This CheckedDistributedStorageAdmin
is the main component in this PR.
This class wraps the DistributedStorageAdmin
implementations, and adds some checks to them.
/** | ||
* Whether to check if the namespace exists or not. Set false when the storage does not support | ||
* namespaces. | ||
*/ | ||
private final boolean checkNamespace; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have several implementations that don't support namespaces (DynamoDB, SQLite), we set it to false for them.
Maybe we can remove it after supporting the namespace listing feature. (CC: @Torch3333 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can remove it after supporting the namespace listing feature.
Agreed.
} | ||
|
||
@Override | ||
public void addNewColumnToTable( | ||
String namespace, String table, String columnName, DataType columnType) | ||
throws ExecutionException { | ||
try { | ||
if (getTableMetadata(namespace, table).getColumnNames().contains(columnName)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have checks in CheckedDistributedStorageAdmin
, removed these checks from the admin implementations.
@@ -54,18 +54,30 @@ public ConsensusCommitAdmin(DatabaseConfig databaseConfig) { | |||
|
|||
@Override | |||
public void createCoordinatorTables(Map<String, String> options) throws ExecutionException { | |||
if (coordinatorTablesExist()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, added some checks to ConsensusCommitAdmin
.
4c46db7
to
32f4cc4
Compare
throw new IllegalArgumentException("Namespace does not exist: " + namespace); | ||
} | ||
if (tableExists(namespace, table)) { | ||
throw new IllegalArgumentException("Table already exists: " + namespace + "." + table); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw new IllegalArgumentException("Table already exists: " + namespace + "." + table); | |
throw new IllegalArgumentException("Table already exists: " + ScalarDbUtils.getFullTableName(namespace, table)); |
Should the utility function be used all the time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in fcb2338. Thanks.
@Override | ||
public void dropTable(String namespace, String table) throws ExecutionException { | ||
if (!tableExists(namespace, table)) { | ||
throw new IllegalArgumentException("Table does not exist: " + namespace + "." + table); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw new IllegalArgumentException("Table does not exist: " + namespace + "." + table); | |
throw new IllegalArgumentException("Table does not exist: " + ScalarDbUtils.getFullTableName(namespace, table)); |
Likewise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in fcb2338. Thanks.
@Override | ||
public void truncateTable(String namespace, String table) throws ExecutionException { | ||
if (!tableExists(namespace, table)) { | ||
throw new IllegalArgumentException("Table does not exist: " + namespace + "." + table); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw new IllegalArgumentException("Table does not exist: " + namespace + "." + table); | |
throw new IllegalArgumentException("Table does not exist: " + ScalarDbUtils.getFullTableName(namespace, table)); |
Likewise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in fcb2338. Thanks.
public void dropIndex(String namespace, String table, String columnName) | ||
throws ExecutionException { | ||
if (!tableExists(namespace, table)) { | ||
throw new IllegalArgumentException("Table does not exist: " + namespace + "." + table); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw new IllegalArgumentException("Table does not exist: " + namespace + "." + table); | |
throw new IllegalArgumentException("Table does not exist: " + ScalarDbUtils.getFullTableName(namespace, table)); |
Likewise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in fcb2338. Thanks.
@@ -165,6 +177,9 @@ public void addNewColumnToTable( | |||
String namespace, String table, String columnName, DataType columnType) | |||
throws ExecutionException { | |||
TableMetadata tableMetadata = getTableMetadata(namespace, table); | |||
if (tableMetadata == null) { | |||
throw new IllegalArgumentException("Table does not exist: " + namespace + "." + table); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw new IllegalArgumentException("Table does not exist: " + namespace + "." + table); | |
throw new IllegalArgumentException("Table does not exist: " + ScalarDbUtils.getFullTableName(namespace, table)); |
Likewise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in fbe7195. Thanks.
/** | ||
* Whether to check if the namespace exists or not. Set false when the storage does not support | ||
* namespaces. | ||
*/ | ||
private final boolean checkNamespace; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can remove it after supporting the namespace listing feature.
Agreed.
String namespace, String table, TableMetadata metadata, Map<String, String> options) | ||
throws ExecutionException { | ||
if (checkNamespace && !namespaceExists(namespace)) { | ||
throw new IllegalArgumentException("Namespace does not exist: " + namespace); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the underlying admin is the DynamoAdmin used with a namespace prefix, the value of the namespace
argument used in this class here is not prefixed. The error message may be confusing since it will mention the unprefixed namespace.
For clarity, mentioning the prefixed namespace in the error message throughout this class would be great. What do you think ?
I have the same concern about using the unprefixed namespace in the error message in the ConsensusCommitAdmin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think since users pass the logical name (the unprefixed name) to the APIs, I feel it's consistent and natural for the error messages to use the logical name. In CheckedDistributedStorageAdmin
, the IllegalArgumentException
always has the logical name. However, when an error occurs, the message of the exception also uses the logical name, but the cause of the exception should have the physical name. So we can use it for debugging.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, this makes sense. Let's keep it as is. Thank you.
} | ||
|
||
@Override | ||
public void dropTable(String namespace, String table) throws ExecutionException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These xxxxTable()
and xxxxIndex()
should check namespace as well as createTable()
? I think either is fine as long as they're consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the operations that assumes the the target table exists, we don't have the namespace check. In that sense, they should be consistent. And the table check contains the namespace check, so I think that should be okay.
@@ -77,7 +77,7 @@ public String dropNamespaceSql(String namespace) { | |||
@Override | |||
public void dropNamespaceTranslateSQLException(SQLException e, String namespace) | |||
throws ExecutionException { | |||
throw new ExecutionException(String.format("error dropping the schema %s", namespace), e); | |||
throw new ExecutionException("dropping the schema failed: %s" + namespace, e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%s
should be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah my bad. Good catch! Thanks. Fixed in 87166ae.
@@ -86,7 +86,7 @@ public String dropNamespaceSql(String namespace) { | |||
@Override | |||
public void dropNamespaceTranslateSQLException(SQLException e, String namespace) | |||
throws ExecutionException { | |||
throw new ExecutionException(String.format("error dropping the schema %s", namespace), e); | |||
throw new ExecutionException("dropping the schema failed: %s" + namespace, e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 87166ae. Thanks.
@@ -78,7 +78,7 @@ public String dropNamespaceSql(String namespace) { | |||
@Override | |||
public void dropNamespaceTranslateSQLException(SQLException e, String namespace) | |||
throws ExecutionException { | |||
throw new ExecutionException(String.format("error dropping the schema %s", namespace), e); | |||
throw new ExecutionException("dropping the schema failed: %s" + namespace, e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 87166ae. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thank you!
(Sorry for the late review...)
For your reference, I was able to get the error as expected as follows (i.e., the bug I found is fixed).
- Create schemas/tables on MySQL
0: scalardb> 0: scalardb> CREATE COORDINATOR TABLES; No rows affected (1.027 seconds) 0: scalardb> 0: scalardb> 0: scalardb> CREATE NAMESPACE s0; No rows affected (0.03 seconds) 0: scalardb> 0: scalardb> 0: scalardb> CREATE NAMESPACE s1; No rows affected (0.044 seconds) 0: scalardb> 0: scalardb> 0: scalardb> CREATE TABLE s0.t0 (c1 INT PRIMARY KEY, c2 INT); No rows affected (0.426 seconds) 0: scalardb> 0: scalardb> 0: scalardb> CREATE TABLE s1.t1 (c1 INT PRIMARY KEY, c2 INT); No rows affected (0.302 seconds) 0: scalardb>
- Check schemas/tables on MySQL
mysql> show databases; +--------------------+ | Database | +--------------------+ | coordinator | | information_schema | | my_database | | mysql | | performance_schema | | s0 | | s1 | | scalardb | | sys | +--------------------+ 9 rows in set (0.00 sec) mysql> mysql> show tables from s0; +--------------+ | Tables_in_s0 | +--------------+ | t0 | +--------------+ 1 row in set (0.00 sec) mysql> mysql> show tables from s1; +--------------+ | Tables_in_s1 | +--------------+ | t1 | +--------------+ 1 row in set (0.00 sec)
- Check table metadata
mysql> select * from scalardb.metadata; +-------------------+------------------------+-----------+-----------+------------------+---------+------------------+ | full_table_name | column_name | data_type | key_type | clustering_order | indexed | ordinal_position | +-------------------+------------------------+-----------+-----------+------------------+---------+------------------+ | coordinator.state | tx_created_at | BIGINT | NULL | NULL | 0 | 3 | | coordinator.state | tx_id | TEXT | PARTITION | NULL | 0 | 1 | | coordinator.state | tx_state | INT | NULL | NULL | 0 | 2 | | s0.t0 | before_c2 | INT | NULL | NULL | 0 | 13 | | s0.t0 | before_tx_committed_at | BIGINT | NULL | NULL | 0 | 12 | | s0.t0 | before_tx_id | TEXT | NULL | NULL | 0 | 8 | | s0.t0 | before_tx_prepared_at | BIGINT | NULL | NULL | 0 | 11 | | s0.t0 | before_tx_state | INT | NULL | NULL | 0 | 9 | | s0.t0 | before_tx_version | INT | NULL | NULL | 0 | 10 | | s0.t0 | c1 | INT | PARTITION | NULL | 0 | 1 | | s0.t0 | c2 | INT | NULL | NULL | 0 | 2 | | s0.t0 | tx_committed_at | BIGINT | NULL | NULL | 0 | 7 | | s0.t0 | tx_id | TEXT | NULL | NULL | 0 | 3 | | s0.t0 | tx_prepared_at | BIGINT | NULL | NULL | 0 | 6 | | s0.t0 | tx_state | INT | NULL | NULL | 0 | 4 | | s0.t0 | tx_version | INT | NULL | NULL | 0 | 5 | | s1.t1 | before_c2 | INT | NULL | NULL | 0 | 13 | | s1.t1 | before_tx_committed_at | BIGINT | NULL | NULL | 0 | 12 | | s1.t1 | before_tx_id | TEXT | NULL | NULL | 0 | 8 | | s1.t1 | before_tx_prepared_at | BIGINT | NULL | NULL | 0 | 11 | | s1.t1 | before_tx_state | INT | NULL | NULL | 0 | 9 | | s1.t1 | before_tx_version | INT | NULL | NULL | 0 | 10 | | s1.t1 | c1 | INT | PARTITION | NULL | 0 | 1 | | s1.t1 | c2 | INT | NULL | NULL | 0 | 2 | | s1.t1 | tx_committed_at | BIGINT | NULL | NULL | 0 | 7 | | s1.t1 | tx_id | TEXT | NULL | NULL | 0 | 3 | | s1.t1 | tx_prepared_at | BIGINT | NULL | NULL | 0 | 6 | | s1.t1 | tx_state | INT | NULL | NULL | 0 | 4 | | s1.t1 | tx_version | INT | NULL | NULL | 0 | 5 | +-------------------+------------------------+-----------+-----------+------------------+---------+------------------+ 29 rows in set (0.00 sec)
- Drop namespaces with/without
CASCADE
option0: scalardb> DROP NAMESPACE s0; Error: Invalid query (INVALID_ARGUMENT: Namespace is not empty: s0, [t0]) (state=42000,code=501) 0: scalardb> 0: scalardb> DROP NAMESPACE s1 CASCADE; No rows affected (0.149 seconds) 0: scalardb>
- When I run the
DROP SCHEMA
withoutCASCADE
option, ScalarDB returns error as expected.
- When I run the
- Check schemas/tables on MySQL
mysql> show databases; +--------------------+ | Database | +--------------------+ | coordinator | | information_schema | | my_database | | mysql | | performance_schema | | s0 | | scalardb | | sys | +--------------------+ 8 rows in set (0.00 sec) mysql> mysql> show tables from s0; +--------------+ | Tables_in_s0 | +--------------+ | t0 | +--------------+ 1 row in set (0.00 sec)
- Check table metadata
mysql> select * from scalardb.metadata; +-------------------+------------------------+-----------+-----------+------------------+---------+------------------+ | full_table_name | column_name | data_type | key_type | clustering_order | indexed | ordinal_position | +-------------------+------------------------+-----------+-----------+------------------+---------+------------------+ | coordinator.state | tx_created_at | BIGINT | NULL | NULL | 0 | 3 | | coordinator.state | tx_id | TEXT | PARTITION | NULL | 0 | 1 | | coordinator.state | tx_state | INT | NULL | NULL | 0 | 2 | | s0.t0 | before_c2 | INT | NULL | NULL | 0 | 13 | | s0.t0 | before_tx_committed_at | BIGINT | NULL | NULL | 0 | 12 | | s0.t0 | before_tx_id | TEXT | NULL | NULL | 0 | 8 | | s0.t0 | before_tx_prepared_at | BIGINT | NULL | NULL | 0 | 11 | | s0.t0 | before_tx_state | INT | NULL | NULL | 0 | 9 | | s0.t0 | before_tx_version | INT | NULL | NULL | 0 | 10 | | s0.t0 | c1 | INT | PARTITION | NULL | 0 | 1 | | s0.t0 | c2 | INT | NULL | NULL | 0 | 2 | | s0.t0 | tx_committed_at | BIGINT | NULL | NULL | 0 | 7 | | s0.t0 | tx_id | TEXT | NULL | NULL | 0 | 3 | | s0.t0 | tx_prepared_at | BIGINT | NULL | NULL | 0 | 6 | | s0.t0 | tx_state | INT | NULL | NULL | 0 | 4 | | s0.t0 | tx_version | INT | NULL | NULL | 0 | 5 | +-------------------+------------------------+-----------+-----------+------------------+---------+------------------+ 16 rows in set (0.00 sec)
This PR unifies the behavior of the admin implementations (e.g. an error is thrown when dropping a namespace but the namespace has some tables). I'll add inline comments for the details. Please take a look!