Skip to content

Commit

Permalink
[SQLite] Support SAVEPOINT (#11695)
Browse files Browse the repository at this point in the history
- Implement SAVEPOINT for sqlite-based layers
- Add OGRFieldDefn::SetGenerated()/IsGenerated()
  • Loading branch information
elpaso authored Jan 20, 2025
1 parent b05dfb6 commit 8f576c0
Show file tree
Hide file tree
Showing 18 changed files with 814 additions and 190 deletions.
56 changes: 54 additions & 2 deletions autotest/ogr/ogr_gpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -9178,8 +9178,10 @@ def test_ogr_gpkg_read_generated_column(tmp_vsimem):
lyr = ds.GetLayer(0)
assert lyr.GetLayerDefn().GetFieldCount() == 4
assert lyr.GetLayerDefn().GetFieldDefn(2).GetName() == "strfield_generated"
assert lyr.GetLayerDefn().GetFieldDefn(2).IsGenerated()
assert lyr.GetLayerDefn().GetFieldDefn(2).GetType() == ogr.OFTString
assert lyr.GetLayerDefn().GetFieldDefn(3).GetName() == "intfield_generated_stored"
assert lyr.GetLayerDefn().GetFieldDefn(3).IsGenerated()
assert lyr.GetLayerDefn().GetFieldDefn(3).GetType() == ogr.OFTInteger64

f = ogr.Feature(lyr.GetLayerDefn())
Expand All @@ -9191,6 +9193,8 @@ def test_ogr_gpkg_read_generated_column(tmp_vsimem):
assert f["strfield"] == "foo"
assert f["strfield_generated"] == "foo_generated"
assert f["intfield_generated_stored"] == 5
assert f.GetFieldDefnRef(2).IsGenerated()
assert f.GetFieldDefnRef(3).IsGenerated()

assert lyr.SetFeature(f) == ogr.OGRERR_NONE
lyr.ResetReading()
Expand Down Expand Up @@ -10914,8 +10918,56 @@ def test_ogr_gpkg_arrow_stream_numpy_datetime_as_string(tmp_vsimem):
# Test field operations rolling back changes.


def test_ogr_gpkg_field_operations_rollback(tmp_vsimem):
@pytest.mark.parametrize("start_transaction", [False, True])
def test_ogr_gpkg_field_operations_rollback(tmp_vsimem, start_transaction):

filename = str(tmp_vsimem / "test.gpkg")
with ogr.GetDriverByName("GPKG").CreateDataSource(filename) as ds:
ogrtest.check_transaction_rollback(ds, test_geometry=False)
ogrtest.check_transaction_rollback(ds, start_transaction, test_geometry=False)


@pytest.mark.parametrize("start_transaction", [False, True])
def test_ogr_gpkg_field_operations_savepoint_rollback(tmp_vsimem, start_transaction):

filename = str(tmp_vsimem / "test_savepoint.gpkg")
with ogr.GetDriverByName("GPKG").CreateDataSource(filename) as ds:
ogrtest.check_transaction_rollback_with_savepoint(
ds, start_transaction, test_geometry=False
)


@pytest.mark.parametrize("auto_begin_transaction", [False, True])
@pytest.mark.parametrize("start_transaction", [False, True])
@pytest.mark.parametrize(
"release_to,rollback_to,expected",
(
([1], [], ["fld3"]),
([2], [], ["fld3"]),
([3], [], ["fld3"]),
([4], [], ["fld3"]),
([], [1], ["fld1", "fld2", "fld3", "fld4", "fld5"]),
([], [2], ["fld1", "fld3", "fld4", "fld5"]),
([], [3], ["fld1", "fld3", "fld5"]),
([], [4], ["fld3", "fld5"]),
),
)
def test_ogr_gpkg_field_operations_savepoint_release(
tmp_vsimem,
auto_begin_transaction,
start_transaction,
release_to,
rollback_to,
expected,
):

filename = str(tmp_vsimem / "test_savepoint_release.gpkg")
ogrtest.check_transaction_savepoint_release(
filename,
"GPKG",
auto_begin_transaction,
start_transaction,
release_to,
rollback_to,
expected,
test_geometry=False,
)
54 changes: 50 additions & 4 deletions autotest/ogr/ogr_sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -4543,10 +4543,56 @@ def test_ogr_sqlite_schema_override(
#


def test_field_rollback(tmp_path):
@pytest.mark.parametrize("start_transaction", [False, True])
def test_ogr_sqlite_field_operations_rollback(tmp_vsimem, start_transaction):

filename = str(tmp_path / "test_field_rollback.db")
filename = str(tmp_vsimem / "test.db")
with ogr.GetDriverByName("SQLite").CreateDataSource(filename) as ds:
ogrtest.check_transaction_rollback(ds, start_transaction, test_geometry=False)


@pytest.mark.parametrize("start_transaction", [False, True])
def test_ogr_sqlite_field_operations_savepoint_rollback(tmp_vsimem, start_transaction):

# Create a new database.
filename = str(tmp_vsimem / "test_savepoint.db")
with ogr.GetDriverByName("SQLite").CreateDataSource(filename) as ds:
ogrtest.check_transaction_rollback(ds, test_geometry=True)
ogrtest.check_transaction_rollback_with_savepoint(
ds, start_transaction, test_geometry=False
)


@pytest.mark.parametrize("auto_begin_transaction", [False, True])
@pytest.mark.parametrize("start_transaction", [False, True])
@pytest.mark.parametrize(
"release_to,rollback_to,expected",
(
([1], [], ["fld3"]),
([2], [], ["fld3"]),
([3], [], ["fld3"]),
([4], [], ["fld3"]),
([], [1], ["fld1", "fld2", "fld3", "fld4", "fld5"]),
([], [2], ["fld1", "fld3", "fld4", "fld5"]),
([], [3], ["fld1", "fld3", "fld5"]),
([], [4], ["fld3", "fld5"]),
),
)
def test_ogr_sqlite_field_operations_savepoint_release(
tmp_vsimem,
auto_begin_transaction,
start_transaction,
release_to,
rollback_to,
expected,
):

filename = str(tmp_vsimem / "test_savepoint_release.db")
ogrtest.check_transaction_savepoint_release(
filename,
"SQLite",
auto_begin_transaction,
start_transaction,
release_to,
rollback_to,
expected,
test_geometry=False,
)
Loading

0 comments on commit 8f576c0

Please sign in to comment.