-
Notifications
You must be signed in to change notification settings - Fork 92
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
Add support for transactions on datasets #109
Conversation
i think this is a good addition to the crate. could you add some documentation to the methods? |
52e95d2
to
19986c1
Compare
Looking more closely at the GDAL docs, transactions on individual layers are discouraged because they are rarely supported by drivers. So I changed this PR to implement transactions at the dataset level instead, added documentation, and some tests. |
We should probably discuss a better (safer) API. I can think of two approaches: dataset.with_transaction(|| -> Result<()> {
...
}); If the lambda returns An alternative is to have a let transaction = dataset.start_transaction();
...
transaction.commit();
I like this approach better because it's more flexible and needs less nesting. It is also somewhat similar to how // 'dataset is the lifetime of the original Dataset.
struct Transaction<'dataset> {
c_dataset: GDALDatasetH,
committed: bool,
}
impl Dataset {
// Are explicit lifetimes needed?
fn start_transaction(&'dataset mut self) -> Result<Transaction<'dataset>> {
Transaction { c_dataset: self.c_dataset, committed: false }
}
} I'm a bit of a newbie when it comes to good API design in Rust, so any feedback is very welcome. |
First of all, I really like this PR and the idea behind it, unlocking the feature for this crate. Here are my comments:
If you change the tests accordingly, we should see if this works out as intended. We should also address what happens if you start a second transaction on a dataset. With respect to the |
19986c1
to
432631b
Compare
Thanks! I've updated the PR and also added an example/doctest to the docs. The lifetime trick with I got around this by simply adding a The |
b555a60
to
803062a
Compare
src/dataset.rs
Outdated
/// | ||
/// If an error occurs after a successful `start_transaction`, the whole transaction may or may | ||
/// not be implicitly canceled, depending on the driver. For example, the PG driver will cancel | ||
/// it, but the SQLite and GPKG drivers will not. |
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'm surprised this is true for SQLite, which, in general supports transaction rollback. Can you provide any more detail?
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 just copied the relevant portions from the GDAL API docs (with minor wordsmithing) so I have no clue either.
can we change the tests to use GPKG instead of FileGDB? I guess GPKG should be available in most builds since it only requires libsqlite. |
There are already tests using GPKG, but it has actual transaction support (not emulated), so If you don't like to have a test that doesn't test anything on most systems, and requires two hundred stupid fixture files, I agree! I'd be happy to just remove the test and the files. And maybe even remove |
Maybe there is a driver where we don't need 200 files... Could you check this? If there is no alternative we should keep it as well as |
803062a
to
eb30563
Compare
eb30563
to
9a654ff
Compare
In the end, I decided to just get rid of Checking the GDAL source confirmed that FileGDB really is the only driver for which this matters. Most people don't have FileGDB because it's not built-in; you need to download a closed-source SDK and build GDAL from source to enable it. Moreover, I'm not even sure that the test will work: the FileGDB driver only supports version 10 of the format (unlike OpenFileGDB, which supports version 9 as well), and I can't find a way to check which version the example file is without buying ArcGIS. If someone does have FileGDB support and wants to use emulated transactions, they can just use The only remaining use case for I also improved the tests a bit to check that changes are actually commited or rolled back as expected. This added a dev-only dependency on the |
i guess this is the best way to go. FileGDB is probably not relevant when there is OpenFileGDB as well. Thanks for your contribution. |
A must have for performance with some GDAL drivers. Writing 22655 points to a GeoPackage:
I've just copied the C++ API here, but I'm sure there's a more rustilicious way of doing it. Maybe
layer.with_transaction(|| { ... })
, where the lambda returns aResult
, and we commit if it'sOk
and rollback if it'sErr
?If the code can't easily be put into a lambda, I think the simple wrapper functions could still be useful.