blob: c3f5dfb705a5420da6a53878954e3f40d0d62a22 [file] [edit]
/*
* Copyright (C) 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SRC_PERFETTO_SQL_ANALYSIS_RELATION_H_
#define SRC_PERFETTO_SQL_ANALYSIS_RELATION_H_
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "perfetto/ext/base/status_or.h"
#include "perfetto/ext/base/type_set.h"
struct SyntaqliteParser;
namespace perfetto::perfetto_sql::analysis {
// A node in a caller-owned Syntaqlite parse tree.
struct SqlNode {
SyntaqliteParser* parser;
uint32_t id;
};
// How a leaf relation column is stored, as declared by the catalog. Mirrors
// the storage vocabulary of the engine behind the catalog without depending
// on it.
struct Id {};
struct Uint32 {};
struct Int32 {};
struct Int64 {};
struct Double {};
struct String {};
using ColumnType = base::TypeSet<Id, Uint32, Int32, Int64, Double, String>;
// A leaf relation whose columns can be used as lineage origins.
struct LeafColumn {
std::string_view name;
// Nothing when the catalog does not know how the column is stored.
std::optional<ColumnType> type;
};
struct LeafRelation {
std::string_view name;
std::vector<LeafColumn> columns;
};
// Supplies the schema objects referenced by parsed queries. Returned leaf
// strings only need to remain valid for the duration of an Analyze call.
class Catalog {
public:
virtual ~Catalog();
virtual std::optional<LeafRelation> FindLeafRelation(
std::string_view name) const = 0;
virtual std::optional<std::string> FindViewSql(
std::string_view name) const = 0;
};
struct ColumnOrigin {
std::string_view relation_name;
std::string_view column_name;
std::optional<ColumnType> type;
// Two origins naming the same column always store it the same way, so the
// type does not participate.
bool operator==(const ColumnOrigin& other) const {
return relation_name == other.relation_name &&
column_name == other.column_name;
}
};
struct ColumnLineage {
std::string_view output_name;
// Empty when the expression cannot be traced to a known leaf column. USING
// columns and compound queries can have more than one origin.
std::vector<ColumnOrigin> origins;
// The type every origin agrees on, or nothing when the column has no
// origins, an origin is untyped, or the origins disagree.
std::optional<ColumnType> type() const;
};
// The lineage of a query result considered as a relation. All strings are
// owned by this object.
class RelationLineage {
public:
RelationLineage(RelationLineage&&) noexcept;
RelationLineage& operator=(RelationLineage&&) noexcept;
~RelationLineage();
RelationLineage(const RelationLineage&) = delete;
RelationLineage& operator=(const RelationLineage&) = delete;
const std::vector<ColumnLineage>& columns() const;
// The leaf relation whose rows map directly to the output rows, or nothing
// when the query filters, joins, groups, limits or computes values.
std::optional<std::string_view> row_origin() const;
private:
class Storage;
explicit RelationLineage(std::unique_ptr<Storage>);
std::unique_ptr<Storage> storage_;
friend class RelationAnalyzer;
};
// Computes relation and column lineage over caller-owned parse trees.
class RelationAnalyzer {
public:
explicit RelationAnalyzer(const Catalog&);
~RelationAnalyzer();
RelationAnalyzer(const RelationAnalyzer&) = delete;
RelationAnalyzer& operator=(const RelationAnalyzer&) = delete;
base::StatusOr<RelationLineage> AnalyzeQuery(SqlNode);
base::StatusOr<RelationLineage> AnalyzeRelation(std::string_view name);
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace perfetto::perfetto_sql::analysis
#endif // SRC_PERFETTO_SQL_ANALYSIS_RELATION_H_