Skip to content

Commit 894acc3

Browse files
authored
feat: Add lenient and conjunction mode options to parse (#63)
1 parent b468dac commit 894acc3

3 files changed

Lines changed: 112 additions & 7 deletions

File tree

src/Extensions/ParadeDbFunctionsExtensions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,15 @@ public static bool Exists<TProperty>(this DbFunctions _, TProperty property) =>
155155
public static bool Parse<TProperty>(this DbFunctions _, TProperty property, string pattern) =>
156156
throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(Parse)));
157157

158+
[DbFunction]
159+
public static bool Parse<TProperty>(
160+
this DbFunctions _,
161+
TProperty property,
162+
string pattern,
163+
bool? lenient = null,
164+
bool? conjunctionMode = null
165+
) => throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(Parse)));
166+
158167
[DbFunction]
159168
public static bool Regex<TProperty>(
160169
this DbFunctions _,

src/Internal/Query/Translator.cs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,7 @@ IRelationalTypeMappingSource typeMappingSource
8787
),
8888
nameof(ParadeDbFunctionsExtensions.Parse) => BuildQueryBuilderFunction(
8989
arguments[1],
90-
_sqlExpressionFactory.Function(
91-
name: "pdb.parse",
92-
nullable: false,
93-
arguments: [arguments[2]],
94-
argumentsPropagateNullability: [false],
95-
returnType: typeof(bool)
96-
)
90+
BuildParse(arguments)
9791
),
9892
nameof(ParadeDbFunctionsExtensions.Regex) => BuildQueryBuilderFunction(
9993
arguments[1],
@@ -159,6 +153,40 @@ IRelationalTypeMappingSource typeMappingSource
159153
};
160154
}
161155

156+
private SqlExpression BuildParse(IReadOnlyList<SqlExpression> arguments)
157+
{
158+
List<SqlExpression> args = [_sqlExpressionFactory.ApplyDefaultTypeMapping(arguments[2])];
159+
List<string?> argNames = [null];
160+
161+
Add(3, "lenient");
162+
Add(4, "conjunction_mode");
163+
164+
void Add(int index, string name)
165+
{
166+
if (
167+
arguments.Count <= index
168+
|| arguments[index] is SqlConstantExpression { Value: null }
169+
)
170+
{
171+
return;
172+
}
173+
174+
args.Add(_sqlExpressionFactory.ApplyDefaultTypeMapping(arguments[index]));
175+
argNames.Add(name);
176+
}
177+
178+
return PgFunctionExpression.CreateWithNamedArguments(
179+
name: "pdb.parse",
180+
arguments: args,
181+
argumentNames: argNames,
182+
nullable: false,
183+
argumentsPropagateNullability: new bool[args.Count],
184+
builtIn: false,
185+
type: typeof(bool),
186+
typeMapping: null
187+
);
188+
}
189+
162190
private SqlExpression BuildPhrasePrefix(IReadOnlyList<SqlExpression> arguments)
163191
{
164192
List<SqlExpression> args = [arguments[2]];

tests/QueryTests.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,74 @@ WHERE m.description @@@ pdb.parse('description:(sleek shoes) AND rating:>3')
16361636
await query.ToListAsync();
16371637
}
16381638

1639+
[Test]
1640+
public async Task Parse_Lenient()
1641+
{
1642+
await using var context = DbFixture.CreateContext();
1643+
1644+
var query = context
1645+
.MockItems.Where(p => EF.Functions.Parse(p.Description, "sleek shoes", lenient: true))
1646+
.Select(p => p.Description);
1647+
1648+
var sql = """
1649+
SELECT m.description
1650+
FROM mock_items AS m
1651+
WHERE m.description @@@ pdb.parse('sleek shoes', lenient => TRUE)
1652+
""";
1653+
1654+
AssertSql(query, sql);
1655+
await query.ToListAsync();
1656+
}
1657+
1658+
[Test]
1659+
public async Task Parse_ConjunctionMode()
1660+
{
1661+
await using var context = DbFixture.CreateContext();
1662+
1663+
var query = context
1664+
.MockItems.Where(p =>
1665+
EF.Functions.Parse(p.Description, "description:(sleek shoes)", null, true)
1666+
)
1667+
.Select(p => p.Description);
1668+
1669+
var sql = """
1670+
SELECT m.description
1671+
FROM mock_items AS m
1672+
WHERE m.description @@@ pdb.parse('description:(sleek shoes)', conjunction_mode => TRUE)
1673+
""";
1674+
1675+
AssertSql(query, sql);
1676+
await query.ToListAsync();
1677+
}
1678+
1679+
[Test]
1680+
public async Task Parse_WithVariableParameters()
1681+
{
1682+
await using var context = DbFixture.CreateContext();
1683+
1684+
string pattern = "description:(sleek shoes)";
1685+
bool lenient = true;
1686+
bool conjunctionMode = true;
1687+
1688+
var query = context
1689+
.MockItems.Where(p =>
1690+
EF.Functions.Parse(p.Description, pattern, lenient, conjunctionMode)
1691+
)
1692+
.Select(p => p.Description);
1693+
1694+
var sql = """
1695+
-- @pattern='description:(sleek shoes)'
1696+
-- @lenient='True' (Nullable = true)
1697+
-- @conjunctionMode='True' (Nullable = true)
1698+
SELECT m.description
1699+
FROM mock_items AS m
1700+
WHERE m.description @@@ pdb.parse(@pattern, lenient => @lenient, conjunction_mode => @conjunctionMode)
1701+
""";
1702+
1703+
AssertSql(query, sql);
1704+
await query.ToListAsync();
1705+
}
1706+
16391707
[Test]
16401708
public async Task RegexQuery()
16411709
{

0 commit comments

Comments
 (0)