Skip to content

Commit b7a9ef1

Browse files
author
Jérémie Pardou
committed
Merge branch 'fix-formula-recursion-error' into 'develop'
Fix formula recursion error Closes #2506 See merge request baserow/baserow!2313
2 parents c214c8c + c14a9d2 commit b7a9ef1

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

backend/src/baserow/contrib/integrations/local_baserow/service_types.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,7 @@ def resolve_service_formulas(
12141214
resolved_values = super().resolve_service_formulas(service, dispatch_context)
12151215
field_mappings = service.field_mappings.select_related("field").all()
12161216
for field_mapping in field_mappings:
1217+
dispatch_context.reset_call_stack()
12171218
try:
12181219
resolved_values[field_mapping.id] = resolve_formula(
12191220
field_mapping.value,
@@ -1229,7 +1230,7 @@ def resolve_service_formulas(
12291230
except Exception as e:
12301231
message = (
12311232
"Unknown error in formula for "
1232-
f"field {field_mapping.field.name}({field_mapping.field.id})"
1233+
f"field {field_mapping.field.name}({field_mapping.field.id}): {str(e)}"
12331234
)
12341235
raise ServiceImproperlyConfigured(message) from e
12351236

@@ -1239,6 +1240,7 @@ def resolve_service_formulas(
12391240
return resolved_values
12401241

12411242
try:
1243+
dispatch_context.reset_call_stack()
12421244
resolved_values["row_id"] = ensure_integer(
12431245
resolve_formula(
12441246
service.row_id,
@@ -1258,6 +1260,7 @@ def resolve_service_formulas(
12581260
raise ServiceImproperlyConfigured(
12591261
f"The `row_id` formula can't be resolved: {e}"
12601262
)
1263+
12611264
return resolved_values
12621265

12631266
def dispatch_data(
@@ -1282,6 +1285,7 @@ def dispatch_data(
12821285

12831286
field_values = {}
12841287
field_mappings = service.field_mappings.select_related("field").all()
1288+
12851289
for field_mapping in field_mappings:
12861290
if field_mapping.id not in resolved_values:
12871291
continue
@@ -1296,11 +1300,7 @@ def dispatch_data(
12961300
if field_type.read_only:
12971301
continue
12981302

1299-
resolved_value = resolve_formula(
1300-
field_mapping.value,
1301-
formula_runtime_function_registry,
1302-
dispatch_context,
1303-
)
1303+
resolved_value = resolved_values[field_mapping.id]
13041304

13051305
# Transform and validate the resolved value with the field type's DRF field.
13061306
serializer_field = field_type.get_serializer_field(field.specific)
@@ -1326,10 +1326,10 @@ def dispatch_data(
13261326
values=field_values,
13271327
values_already_prepared=True,
13281328
)
1329-
except RowDoesNotExist:
1329+
except RowDoesNotExist as exc:
13301330
raise ServiceImproperlyConfigured(
13311331
f"The row with id {resolved_values['row_id']} does not exist."
1332-
)
1332+
) from exc
13331333
else:
13341334
row = RowHandler().create_row(
13351335
user=integration.authorized_user,

backend/tests/baserow/contrib/integrations/local_baserow/test_service_types.py

+58
Original file line numberDiff line numberDiff line change
@@ -2006,6 +2006,64 @@ def test_local_baserow_upsert_row_service_dispatch_data_with_row_id(
20062006
assert getattr(row, cost.db_column) == fake_request.data["page_parameter"]["id"]
20072007

20082008

2009+
@pytest.mark.django_db
2010+
def test_local_baserow_upsert_row_service_dispatch_data_with_multiple_formulas(
2011+
data_fixture,
2012+
):
2013+
user = data_fixture.create_user()
2014+
builder = data_fixture.create_builder_application(user=user)
2015+
page = data_fixture.create_builder_page(builder=builder)
2016+
integration = data_fixture.create_local_baserow_integration(
2017+
application=builder, user=user, authorized_user=user
2018+
)
2019+
database = data_fixture.create_database_application(workspace=builder.workspace)
2020+
table = TableHandler().create_table_and_fields(
2021+
user=user,
2022+
database=database,
2023+
name=data_fixture.fake.name(),
2024+
fields=[
2025+
("Cost", "number", {}),
2026+
("Name", "text", {}),
2027+
],
2028+
)
2029+
cost = table.field_set.get(name="Cost")
2030+
name = table.field_set.get(name="Name")
2031+
row = RowHandler().create_row(
2032+
user=user,
2033+
table=table,
2034+
values={cost.db_column: 5, name.db_column: "test"},
2035+
)
2036+
2037+
data_source = data_fixture.create_builder_local_baserow_get_row_data_source(
2038+
page=page, table=table, integration=integration
2039+
)
2040+
2041+
service = data_fixture.create_local_baserow_upsert_row_service(
2042+
table=table,
2043+
row_id=f'get("data_source.{data_source.id}.id")',
2044+
integration=integration,
2045+
)
2046+
service_type = service.get_type()
2047+
service.field_mappings.create(
2048+
field=cost, value=f'get("data_source.{data_source.id}.{cost.db_column}")'
2049+
)
2050+
service.field_mappings.create(
2051+
field=name, value=f'get("data_source.{data_source.id}.{name.db_column}")'
2052+
)
2053+
2054+
fake_request = Mock()
2055+
fake_request.data = {"page_parameter": {"id": 10}}
2056+
2057+
dispatch_context = BuilderDispatchContext(fake_request, page)
2058+
dispatch_values = service_type.resolve_service_formulas(service, dispatch_context)
2059+
dispatch_data = service_type.dispatch_data(
2060+
service, dispatch_values, dispatch_context
2061+
)
2062+
2063+
row.refresh_from_db()
2064+
assert getattr(row, cost.db_column) == 5
2065+
2066+
20092067
@pytest.mark.django_db
20102068
def test_local_baserow_upsert_row_service_dispatch_data_with_unknown_row_id(
20112069
data_fixture,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "bug",
3+
"message": "Fix formula recursion error in create/update row action when using multiple formule with the same data source",
4+
"issue_number": 2506,
5+
"bullet_points": [],
6+
"created_at": "2024-04-26"
7+
}

0 commit comments

Comments
 (0)