1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SRC_TRACE_PROCESSOR_PERFETTO_SQL_PARSER_PERFETTO_SQL_PARSER_H_ 18 #define SRC_TRACE_PROCESSOR_PERFETTO_SQL_PARSER_PERFETTO_SQL_PARSER_H_ 19 20 #include <memory> 21 #include <optional> 22 #include <string> 23 #include <utility> 24 #include <variant> 25 #include <vector> 26 27 #include "perfetto/base/logging.h" 28 #include "perfetto/ext/base/flat_hash_map.h" 29 #include "src/trace_processor/perfetto_sql/grammar/perfettosql_grammar_interface.h" 30 #include "src/trace_processor/perfetto_sql/parser/function_util.h" 31 #include "src/trace_processor/perfetto_sql/preprocessor/perfetto_sql_preprocessor.h" 32 #include "src/trace_processor/sqlite/sql_source.h" 33 #include "src/trace_processor/util/sql_argument.h" 34 35 namespace perfetto::trace_processor { 36 37 // Parser for PerfettoSQL statements. This class provides an iterator-style 38 // interface for reading all PerfettoSQL statements from a block of SQL. 39 // 40 // Usage: 41 // PerfettoSqlParser parser(my_sql_string.c_str()); 42 // while (parser.Next()) { 43 // auto& stmt = parser.statement(); 44 // // Handle |stmt| here 45 // } 46 // RETURN_IF_ERROR(r.status()); 47 class PerfettoSqlParser { 48 public: 49 // Indicates that the specified SQLite SQL was extracted directly from a 50 // PerfettoSQL statement and should be directly executed with SQLite. 51 struct SqliteSql {}; 52 // Indicates that the specified SQL was a CREATE PERFETTO FUNCTION statement 53 // with the following parameters. 54 struct CreateFunction { 55 struct Returns { 56 bool is_table; 57 // Only set when `is_table` is false. 58 sql_argument::Type scalar_type; 59 // Only set when `is_table` is true. 60 std::vector<sql_argument::ArgumentDefinition> table_columns; 61 }; 62 bool replace; 63 FunctionPrototype prototype; 64 Returns returns; 65 SqlSource sql; 66 std::string description; 67 }; 68 // Indicates that the specified SQL was a CREATE PERFETTO TABLE statement 69 // with the following parameters. 70 struct CreateTable { 71 bool replace; 72 std::string name; 73 std::vector<sql_argument::ArgumentDefinition> schema; 74 // SQL source for the select statement. 75 SqlSource sql; 76 }; 77 // Indicates that the specified SQL was a CREATE PERFETTO VIEW statement 78 // with the following parameters. 79 struct CreateView { 80 bool replace; 81 std::string name; 82 std::vector<sql_argument::ArgumentDefinition> schema; 83 // SQL source for the select statement. 84 SqlSource sql; 85 // SQL source for the CREATE VIEW statement. 86 SqlSource create_view_sql; 87 }; 88 // Indicates that the specified SQL was a CREATE PERFETTO INDEX statement 89 // with the following parameters. 90 struct CreateIndex { 91 bool replace; 92 std::string name; 93 std::string table_name; 94 std::vector<std::string> col_names; 95 }; 96 // Indicates that the specified SQL was a DROP PERFETTO INDEX statement 97 // with the following parameters. 98 struct DropIndex { 99 std::string name; 100 std::string table_name; 101 }; 102 // Indicates that the specified SQL was a INCLUDE PERFETTO MODULE statement 103 // with the following parameter. 104 struct Include { 105 std::string key; 106 }; 107 // Indicates that the specified SQL was a CREATE PERFETTO MACRO statement 108 // with the following parameter. 109 struct CreateMacro { 110 bool replace; 111 SqlSource name; 112 std::vector<std::pair<SqlSource, SqlSource>> args; 113 SqlSource returns; 114 SqlSource sql; 115 }; 116 117 using Statement = std::variant<CreateFunction, 118 CreateIndex, 119 CreateMacro, 120 CreateTable, 121 CreateView, 122 DropIndex, 123 Include, 124 SqliteSql>; 125 126 // Creates a new SQL parser with the a block of PerfettoSQL statements. 127 // Concretely, the passed string can contain >1 statement. 128 explicit PerfettoSqlParser( 129 SqlSource, 130 const base::FlatHashMap<std::string, PerfettoSqlPreprocessor::Macro>&); 131 132 ~PerfettoSqlParser(); 133 134 PerfettoSqlParser(const PerfettoSqlParser&) = delete; 135 PerfettoSqlParser& operator=(const PerfettoSqlParser&) = delete; 136 137 PerfettoSqlParser(PerfettoSqlParser&&) = delete; 138 PerfettoSqlParser& operator=(PerfettoSqlParser&&) = delete; 139 140 // Attempts to parse to the next statement in the SQL. Returns true if 141 // a statement was successfully parsed and false if EOF was reached or the 142 // statement was not parsed correctly. 143 // 144 // Note: if this function returns false, callers *must* call |status()|: it 145 // is undefined behaviour to not do so. 146 bool Next(); 147 148 // Returns the current statement which was parsed. This function *must not* be 149 // called unless |Next()| returned true. 150 const Statement& statement() const; 151 152 // Returns the full statement which was parsed. This should return 153 // |statement()| and Perfetto SQL code that's in front. This function *must 154 // not* be called unless |Next()| returned true. statement_sql()155 const SqlSource& statement_sql() const { 156 PERFETTO_CHECK(statement_sql_); 157 return *statement_sql_; 158 } 159 160 // Returns the error status for the parser. This will be |base::OkStatus()| 161 // until an unrecoverable error is encountered. 162 const base::Status& status() const; 163 164 private: 165 std::unique_ptr<PerfettoSqlParserState> parser_state_; 166 std::optional<SqlSource> statement_sql_; 167 }; 168 169 } // namespace perfetto::trace_processor 170 171 #endif // SRC_TRACE_PROCESSOR_PERFETTO_SQL_PARSER_PERFETTO_SQL_PARSER_H_ 172