Skip to content

Conversation

Flogex
Copy link
Contributor

@Flogex Flogex commented Jun 8, 2023

The DatabaseManager::default_database is returned by DatabaseManager::GetDefaultDatabase when the default catalog in the search path is invalid. In this PR, a method SetDefaultDatabase is added which can be used to change default_database.

With this change, new Connections can use a database as default other than the one that was added first to the DatabaseManager.

The value for default_database can only be changed internally by calling SetDefaultDatabase. There is no SET GLOBAL option for this implemented in this PR.

I have written a unit test for this, but did not know where to put it. If you could tell me a good location for it, I can add it to the PR, too.

The `DatabaseManager::default_database` is returned by `DatabaseManager::GetDefaultDatabase`
when the default catalog in the search path is invalid. This commit adds a method to change
`default_database`.
This makes it possible that new `Connection`s can use a database other than 'memory' as default.
Comment on lines 91 to 100
auto has_active_transaction = context.transaction.HasActiveTransaction();
if (!has_active_transaction) {
context.transaction.BeginTransaction();
}

auto db_entry = GetDatabase(context, new_value);

if (!has_active_transaction) {
context.transaction.ClearTransaction();
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to validate here that the database referred to by new_value actually exists. However, GetDatabase requires a transaction to be active. What is the best way to create a transaction when non is active? Or is there another way to validate that the database exists which does not require to start a transaction?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RunFunctionInTransaction
it's part of ClientContext, client_context.cpp:969

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the hint. I changed the code to use this function.

Copy link
Collaborator

@Mytherin Mytherin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Looks good to me - one comment:

void DatabaseManager::SetDefaultDatabase(ClientContext &context, const string &new_value) {
optional_ptr<AttachedDatabase> db_entry;

context.RunFunctionInTransaction([&]() { db_entry = GetDatabase(context, new_value); });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RunFunctionInTransaction is very heavy-handed. It launches a new transaction if none is active (and commits it afterwards). Generally almost all code in DuckDB (be it parser, planner, optimizer, executor) is run with an active transaction already. Is this necessary only for the unittest? I imagine that when this function is used internally it will be used in locations where a transaction already exists.

Copy link
Contributor Author

@Flogex Flogex Jun 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed I added this to make a unit test case succeed in which I did not start a transaction before calling SetDefaultDatabase. Otherwise, an InternalException with message "TransactionContext::ActiveTransaction called without active transaction" would be thrown. I thought that it would be worth avoiding this exception by starting a new transaction, considering that RunFunctionInTransaction does not have a significant overhead when there is already an active transaction, does it?

But if I understand you correctly, you think that it is better to remove RunFunctionInTransaction and just call GetDatabase directly?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, most functions in the catalog rely on a transaction existing. I think it is better to remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All right, I removed the call to RunFunctionInTransaction. Thank you for the feedback.

Flogex and others added 2 commits June 9, 2023 18:53
…faultDatabase'

Most functions that call 'SetDefaultDatabase' will already have an active transaction,
hence it is not necessary to create a new one.
@Mytherin Mytherin merged commit 3dfd766 into duckdb:master Jun 11, 2023
@Flogex Flogex deleted the fg/set-default-database branch June 11, 2023 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants