Skip to content

Commit da2e224

Browse files
DJGosnellclaude
andcommitted
Fix: Activate carrier path for scalar Set<TValue> chains
SyntacticClauseTranslator was creating SetClauseInfo with an empty parameters list, so BuildChainParameters found no parameter to create a carrier P{n} field from. Add a synthetic ParameterInfo for the value parameter using the column's FullClrType, enabling carrier optimization for all scalar Set chains across all dialects. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2a0a0f1 commit da2e224

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

src/Quarry.Generator/Translation/SyntacticClauseTranslator.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,22 @@ public ClauseInfo Translate(PendingClauseInfo pending)
5151
return new OrderByClauseInfo(sql, pending.IsDescending, _parameters, keyTypeName);
5252
}
5353

54+
if (pending.Kind == ClauseKind.Set)
55+
{
56+
// Set clause: the SQL is the quoted column name, parameter at index 0 is the value.
57+
// Create a synthetic ParameterInfo for the value (second argument to Set<TValue>).
58+
// On the semantic path this comes from GetTypeInfo(valueArg); here we use the
59+
// column's CLR type since Set(u => u.Prop, value) requires matching types.
60+
var valueTypeName = ResolveKeyTypeFromExpression(pending.Expression);
61+
var valueClrType = valueTypeName ?? "object";
62+
var paramIndex = _parameterIndex;
63+
var syntheticParams = new List<ParameterInfo>(_parameters)
64+
{
65+
new ParameterInfo(paramIndex, $"@p{paramIndex}", valueClrType, "value")
66+
};
67+
return new SetClauseInfo(sql, paramIndex, syntheticParams, valueTypeName: valueTypeName);
68+
}
69+
5470
return ClauseInfo.Success(pending.Kind, sql, _parameters);
5571
}
5672
catch (Exception ex)

src/Quarry.Tests/Generation/CarrierGenerationTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,8 @@ public static async Task Test(TestDbContext db, int userId, string newName)
593593
Assert.That(interceptorsTree, Is.Not.Null, "Should generate interceptors file");
594594

595595
var code = interceptorsTree!.GetText().ToString();
596-
// Update chains with Set clauses may not be carrier-eligible (Set uses open generic),
597-
// but the chain should still be analyzed and produce interceptors
596+
// Update chains with scalar Set clauses are carrier-eligible when ValueTypeName is resolved
598597
Assert.That(code, Does.Contain("UPDATE"));
598+
Assert.That(code, Does.Contain("Carrier-Optimized PrebuiltDispatch"));
599599
}
600600
}

0 commit comments

Comments
 (0)