Skip to content

Commit

Permalink
Merge "tp: StructuredQuery supports IS_NULL and IS_NOT_NULL" into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Treehugger Robot authored and Gerrit Code Review committed Jan 23, 2025
2 parents a829742 + b4d234a commit a6cc81e
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 12 deletions.
9 changes: 6 additions & 3 deletions protos/perfetto/perfetto_sql/structured_query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -211,15 +211,18 @@ message PerfettoSqlStructuredQuery {
LESS_THAN_EQUAL = 4;
GREATER_THAN = 5;
GREATER_THAN_EQUAL = 6;
IS_NULL = 8;
IS_NOT_NULL = 9;

// Unix GLOB. Only makes sense for string columns.
GLOB = 7;
}
optional Operator op = 2;

// The RHS for filtering. All values specfied here will be ORed together
// allowing easy IN and GLOB IN filtering. At least one of these fields
// must be non-empty. Only the first non-empty field will be considered.
// The RHS for filtering. All values specified here will be ORed together
// allowing easy IN and GLOB IN filtering. If operation is different than
// IS_NULL or IS_NOT_NULL, at least one of these fields must be non-empty.
// Only the first non-empty field will be considered.
repeated string string_rhs = 3;
repeated double double_rhs = 4;
repeated int64 int64_rhs = 5;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,28 +323,34 @@ base::StatusOr<std::string> GeneratorImpl::Filters(
}

std::string column_name = filter.column_name().ToStdString();
auto op = static_cast<StructuredQuery::Filter::Operator>(filter.op());
ASSIGN_OR_RETURN(std::string op_str, OperatorToString(op));

ASSIGN_OR_RETURN(
std::string op,
OperatorToString(
static_cast<StructuredQuery::Filter::Operator>(filter.op())));
sql += column_name + " " + op + " ";
if (op == StructuredQuery::Filter::Operator::IS_NULL ||
op == StructuredQuery::Filter::Operator::IS_NOT_NULL) {
sql += column_name + " " + op_str;
continue;
}

sql += column_name + " " + op_str + " ";

if (auto srhs = filter.string_rhs(); srhs) {
sql += "'" + (*srhs++).ToStdString() + "'";
for (; srhs; ++srhs) {
sql += " OR " + column_name + " " + op + " '" + (*srhs).ToStdString() +
"'";
sql += " OR " + column_name + " " + op_str + " '" +
(*srhs).ToStdString() + "'";
}
} else if (auto drhs = filter.double_rhs(); drhs) {
sql += std::to_string((*drhs++));
for (; drhs; ++drhs) {
sql += " OR " + column_name + " " + op + " " + std::to_string(*drhs);
sql +=
" OR " + column_name + " " + op_str + " " + std::to_string(*drhs);
}
} else if (auto irhs = filter.int64_rhs(); irhs) {
sql += std::to_string(*irhs++);
for (; irhs; ++irhs) {
sql += " OR " + column_name + " " + op + " " + std::to_string(*irhs);
sql +=
" OR " + column_name + " " + op_str + " " + std::to_string(*irhs);
}
} else {
return base::ErrStatus("Filter must specify a right-hand side");
Expand Down Expand Up @@ -459,6 +465,10 @@ base::StatusOr<std::string> GeneratorImpl::OperatorToString(
return std::string(">=");
case StructuredQuery::Filter::GLOB:
return std::string("GLOB");
case StructuredQuery::Filter::IS_NULL:
return std::string("IS NULL");
case StructuredQuery::Filter::IS_NOT_NULL:
return std::string("IS NOT NULL");
case StructuredQuery::Filter::UNKNOWN:
return base::ErrStatus("Invalid filter operator %d", op);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,76 @@ MATCHER_P(EqualsIgnoringWhitespace, param, "") {
return RemoveAllWhitespace(arg) == RemoveAllWhitespace(param);
}

TEST(StructuredQueryGeneratorTest, Operations) {
StructuredQueryGenerator gen;
auto proto = ToProto(R"(
table: {
table_name: "thread_slice_cpu_time"
module_name: "linux.memory.process"
}
filters: {
column_name: "thread_name"
op: EQUAL
string_rhs: "bar"
}
filters: {
column_name: "thread_name"
op: NOT_EQUAL
string_rhs: "bar"
}
filters: {
column_name: "thread_name"
op: LESS_THAN
string_rhs: "bar"
}
filters: {
column_name: "thread_name"
op: LESS_THAN_EQUAL
string_rhs: "bar"
}
filters: {
column_name: "thread_name"
op: GREATER_THAN
string_rhs: "bar"
}
filters: {
column_name: "thread_name"
op: GREATER_THAN_EQUAL
string_rhs: "bar"
}
filters: {
column_name: "thread_name"
op: IS_NULL
}
filters: {
column_name: "thread_name"
op: IS_NOT_NULL
}
filters: {
column_name: "thread_name"
op: GLOB
string_rhs: "bar"
}
)");
auto ret = gen.Generate(proto.data(), proto.size());
ASSERT_OK_AND_ASSIGN(std::string res, ret);
ASSERT_THAT(res, EqualsIgnoringWhitespace(R"(
WITH sq_0 AS
(
SELECT * FROM thread_slice_cpu_time
WHERE thread_name = 'bar'
AND thread_name != 'bar'
AND thread_name < 'bar'
AND thread_name <= 'bar'
AND thread_name > 'bar'
AND thread_name >= 'bar'
AND thread_name IS NULL
AND thread_name IS NOT NULL
AND thread_name GLOB 'bar'
) SELECT * FROM sq_0
)"));
}

TEST(StructuredQueryGeneratorTest, Smoke) {
StructuredQueryGenerator gen;
auto proto = ToProto(R"(
Expand Down

0 comments on commit a6cc81e

Please sign in to comment.