Skip to content

Commit ca8e666

Browse files
authored
allow empty list for list type parameters (#28947)
1 parent 79fb6bd commit ca8e666

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed

ydb/core/kqp/query_data/kqp_query_data.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ void TQueryData::ValidateParameter(const TString& name, const NKikimrMiniKQL::TT
256256

257257
auto pType = ImportTypeFromProto(type, txTypeEnv);
258258
if (pType == nullptr || !parameterType->IsSameType(*pType)) {
259+
// Allow EmptyList for List<?> parameters
260+
// pType is the expected type from the query declaration (List<?>)
261+
// parameterType is the actual type from the parameter value (EmptyList)
262+
if (pType != nullptr && pType->IsList() && parameterType->IsEmptyList()) {
263+
// EmptyList is compatible with List, this is allowed
264+
return;
265+
}
259266
ythrow yexception() << "Parameter " << name
260267
<< " type mismatch, expected: " << type << ", actual: " << *parameterType;
261268
}

ydb/core/kqp/ut/query/kqp_params_ut.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,144 @@ Y_UNIT_TEST_SUITE(KqpParams) {
14501450
}
14511451
}
14521452

1453+
Y_UNIT_TEST(EmptyListForListParameterExecuteDataQuery) {
1454+
// Test that EmptyList can be passed for List<?> parameters in ExecuteDataQuery
1455+
TKikimrRunner kikimr;
1456+
auto db = kikimr.GetTableClient();
1457+
auto session = db.CreateSession().GetValueSync().GetSession();
1458+
1459+
// Test with prepared query
1460+
{
1461+
auto prepareResult = session.PrepareDataQuery(Q1_(R"(
1462+
DECLARE $x AS List<Uint32>;
1463+
DECLARE $y AS List<Uint32>;
1464+
1465+
SELECT * FROM `/Root/Test` WHERE Group IN $x
1466+
UNION ALL
1467+
SELECT * FROM `/Root/Test` WHERE Group IN $y;
1468+
)")).ExtractValueSync();
1469+
UNIT_ASSERT_VALUES_EQUAL_C(prepareResult.GetStatus(), EStatus::SUCCESS, prepareResult.GetIssues().ToString());
1470+
1471+
auto query = prepareResult.GetQuery();
1472+
auto params = query.GetParamsBuilder()
1473+
.AddParam("$x")
1474+
.EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build())
1475+
.Build()
1476+
.AddParam("$y")
1477+
.EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build())
1478+
.Build()
1479+
.Build();
1480+
1481+
auto result = query.Execute(
1482+
TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx(),
1483+
std::move(params)).ExtractValueSync();
1484+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
1485+
UNIT_ASSERT_VALUES_EQUAL(result.GetResultSet(0).RowsCount(), 0);
1486+
}
1487+
1488+
// Test with ExecuteDataQuery directly
1489+
{
1490+
auto params = db.GetParamsBuilder()
1491+
.AddParam("$x")
1492+
.EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build())
1493+
.Build()
1494+
.AddParam("$y")
1495+
.EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build())
1496+
.Build()
1497+
.Build();
1498+
1499+
auto result = session.ExecuteDataQuery(Q1_(R"(
1500+
DECLARE $x AS List<Uint32>;
1501+
DECLARE $y AS List<Uint32>;
1502+
1503+
SELECT * FROM `/Root/Test` WHERE Group IN $x
1504+
UNION ALL
1505+
SELECT * FROM `/Root/Test` WHERE Group IN $y;
1506+
)"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx(), params).ExtractValueSync();
1507+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
1508+
UNIT_ASSERT_VALUES_EQUAL(result.GetResultSet(0).RowsCount(), 0);
1509+
}
1510+
1511+
// Test with non-empty list to ensure normal lists still work
1512+
{
1513+
auto params = db.GetParamsBuilder()
1514+
.AddParam("$x")
1515+
.BeginList()
1516+
.AddListItem().Uint32(1)
1517+
.EndList()
1518+
.Build()
1519+
.AddParam("$y")
1520+
.EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build())
1521+
.Build()
1522+
.Build();
1523+
1524+
auto result = session.ExecuteDataQuery(Q1_(R"(
1525+
DECLARE $x AS List<Uint32>;
1526+
DECLARE $y AS List<Uint32>;
1527+
1528+
SELECT * FROM `/Root/Test` WHERE Group IN $x
1529+
UNION ALL
1530+
SELECT * FROM `/Root/Test` WHERE Group IN $y;
1531+
)"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx(), params).ExtractValueSync();
1532+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
1533+
}
1534+
}
1535+
1536+
Y_UNIT_TEST(EmptyListForListParameterExecuteQuery) {
1537+
// Test that EmptyList can be passed for List<?> parameters in ExecuteQuery
1538+
TKikimrRunner kikimr;
1539+
auto queryClient = kikimr.GetQueryClient();
1540+
auto tableClient = kikimr.GetTableClient();
1541+
1542+
// Test with ExecuteQuery
1543+
{
1544+
auto params = tableClient.GetParamsBuilder()
1545+
.AddParam("$x")
1546+
.EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build())
1547+
.Build()
1548+
.AddParam("$y")
1549+
.EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build())
1550+
.Build()
1551+
.Build();
1552+
1553+
auto result = queryClient.ExecuteQuery(Q1_(R"(
1554+
DECLARE $x AS List<Uint32>;
1555+
DECLARE $y AS List<Uint32>;
1556+
1557+
SELECT * FROM `/Root/Test` WHERE Group IN $x
1558+
UNION ALL
1559+
SELECT * FROM `/Root/Test` WHERE Group IN $y;
1560+
)"), NYdb::NQuery::TTxControl::BeginTx().CommitTx(), params).ExtractValueSync();
1561+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
1562+
UNIT_ASSERT_VALUES_EQUAL(result.GetResultSets().size(), 1);
1563+
UNIT_ASSERT_VALUES_EQUAL(result.GetResultSet(0).RowsCount(), 0);
1564+
}
1565+
1566+
// Test with non-empty list to ensure normal lists still work
1567+
{
1568+
auto params = tableClient.GetParamsBuilder()
1569+
.AddParam("$x")
1570+
.BeginList()
1571+
.AddListItem().Uint32(1)
1572+
.EndList()
1573+
.Build()
1574+
.AddParam("$y")
1575+
.EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build())
1576+
.Build()
1577+
.Build();
1578+
1579+
auto result = queryClient.ExecuteQuery(Q1_(R"(
1580+
DECLARE $x AS List<Uint32>;
1581+
DECLARE $y AS List<Uint32>;
1582+
1583+
SELECT * FROM `/Root/Test` WHERE Group IN $x
1584+
UNION ALL
1585+
SELECT * FROM `/Root/Test` WHERE Group IN $y;
1586+
)"), NYdb::NQuery::TTxControl::BeginTx().CommitTx(), params).ExtractValueSync();
1587+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
1588+
}
1589+
}
1590+
14531591
}
14541592

14551593
} // namespace NKqp

0 commit comments

Comments
 (0)