mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
query_slicer.cpp
Go to the documentation of this file.
1#include <cstddef>
2#include <cstdlib>
3#include <cstring>
4#include <deque>
5#include <filesystem>
6#include <fstream>
7#include <iostream>
8#include <memory>
10#include <mutable/mutable.hpp>
11#include <mutable/Options.hpp>
13#include <random>
14#include <unordered_map>
15#include <unordered_set>
16#ifdef __BMI2__
17#include <x86intrin.h>
18#endif
19
20
22
23struct args_t
24{
27};
28
29void emit_CSG_queries(std::ostream &out, const m::QueryGraph &G, const m::AdjacencyMatrix &M);
30void emit_query_slice(std::ostream &out, const m::QueryGraph &G, m::Subproblem slice);
31
32void usage(std::ostream &out, const char *name)
33{
34 out << "A tool to generate queries for all connected subgraphs of a query's query graph.\n"
35 << "USAGE:\n\t" << name << " <SCHEMA.sql> [<QUERY.sql>]"
36 << std::endl;
37}
38
39int main(int argc, const char **argv)
40{
41 /*----- Parse command line arguments. ----------------------------------------------------------------------------*/
42 m::ArgParser AP;
44#define ADD(TYPE, VAR, INIT, SHORT, LONG, DESCR, CALLBACK)\
45 VAR = INIT;\
46 {\
47 AP.add<TYPE>(SHORT, LONG, DESCR, CALLBACK);\
48 }
49 /*----- Help message ---------------------------------------------------------------------------------------------*/
50 ADD(bool, args.show_help, false, /* Type, Var, Init */
51 "-h", "--help", /* Short, Long */
52 "prints this help message", /* Description */
53 [&](bool) { args.show_help = true; }); /* Callback */
54 /*----- Parse command line arguments. ----------------------------------------------------------------------------*/
55 AP.parse_args(argc, argv);
56
57 /*----- Help message. -----*/
58 if (args.show_help) {
59 usage(std::cout, argv[0]);
60 std::cout << "WHERE\n" << AP;
61 std::exit(EXIT_SUCCESS);
62 }
63
64 /*----- Validate command line arguments. -------------------------------------------------------------------------*/
65 if (AP.args().size() == 0 or AP.args().size() > 2) {
66 usage(std::cout, argv[0]);
67 std::exit(EXIT_FAILURE);
68 }
69
70 /*----- Configure mutable. ---------------------------------------------------------------------------------------*/
71 m::Options::Get().quiet = true;
72
73 /*----- Load schema. ---------------------------------------------------------------------------------------------*/
74 m::Diagnostic diag(false, std::cout, std::cerr);
75 std::filesystem::path path_to_schema(AP.args()[0]);
76 m::execute_file(diag, path_to_schema);
78 if (not C.has_database_in_use()) {
79 std::cerr << "No database selected.\n";
80 std::exit(EXIT_FAILURE);
81 }
82
83 /*----- Read input from stdin or file. ---------------------------------------------------------------------------*/
84 const std::string input = [&AP]() -> std::string {
85 if (AP.args().size() == 1) {
86 return std::string(std::istreambuf_iterator<char>(std::cin), {});
87 } else {
88 std::filesystem::path path(AP.args()[1]);
89 errno = 0;
90 std::ifstream in(path);
91 if (not in) {
92 std::cerr << "Could not open file '" << path << '\'';
93 const auto errsv = errno;
94 if (errsv)
95 std::cerr << ": " << strerror(errsv);
96 std::cerr << std::endl;
97 std::exit(EXIT_FAILURE);
98 }
99 return std::string(std::istreambuf_iterator<char>(in), {});
100 }
101 }();
102
103 /*----- Parse input. ---------------------------------------------------------------------------------------------*/
104 const std::unique_ptr<m::ast::SelectStmt> select = [&diag, &input]() -> std::unique_ptr<m::ast::SelectStmt> {
105 auto stmt = m::statement_from_string(diag, input);
106 if (not m::is<m::ast::SelectStmt>(stmt.get())) {
107 std::cerr << "Expected a SELECT statement.\n";
108 std::exit(EXIT_FAILURE);
109 }
110 return std::unique_ptr<m::ast::SelectStmt>(m::as<m::ast::SelectStmt>(stmt.release()));
111 }();
112
113 auto G = m::QueryGraph::Build(*select);
114 m::AdjacencyMatrix &M = G->adjacency_matrix();
115
116 /*----- Emit the queries. ----------------------------------------------------------------------------------------*/
117 const Subproblem All = Subproblem::All(G->num_sources());
118 auto emit = [&G](Subproblem S) { emit_query_slice(std::cout, *G, S); };
119 M.for_each_CSG_undirected(All, emit);
120}
121
122void emit_query_slice(std::ostream &out, const m::QueryGraph &G, m::Subproblem slice)
123{
124 /*----- SELECT clause -----*/
125 out << "SELECT COUNT(*)\n";
126
127 /*----- FROM clause -----*/
128 out << "FROM ";
129 for (auto start = slice.begin(), it = start; it != slice.end(); ++it) {
130 if (it != start) out << ", ";
131 const auto source = G.sources()[*it].get();
132 if (const m::BaseTable *T = cast<const m::BaseTable>(source)) {
133 out << T->table().name();
134 if (T->alias().has_value())
135 out << " AS " << T->alias();
136 } else {
137 std::cerr << "ERROR: Nested queries are not supported." << std::endl;
138 std::exit(EXIT_FAILURE);
139 }
140 }
141
142 /*----- WHERE clause -----*/
143 bool is_first_in_where = true;
144
145 /* Joins */
146 for (auto &J : G.joins()) {
147 auto &sources = J->sources();
148 for (auto source : sources) {
149 if (not slice[source.get().id()]) // slice does not contain this source of the join
150 goto skip_join;
151 }
152 if (is_first_in_where) {
153 out << "\nWHERE ";
154 is_first_in_where = false;
155 } else {
156 out << " AND ";
157 }
158 J->condition().to_sql(out);
159skip_join:;
160 }
161
162 /* Conditions */
163 {
164 for (auto idx : slice) {
165 const auto &source = *G.sources()[idx];
166 const auto &selection = source.filter();
167 if (not selection.empty()) {
168 if (is_first_in_where) {
169 out << "\nWHERE ";
170 is_first_in_where = false;
171 } else {
172 out << " AND ";
173 }
174 selection.to_sql(out);
175 }
176 }
177 }
178
179 out << ";\n\n";
180}
int main(void)
struct @5 args
A parser for command line arguments.
Definition: ArgParser.hpp:20
void parse_args(int argc, const char **argv)
Parses the arguments from argv.
Definition: ArgParser.cpp:186
const std::vector< const char * > & args() const
Returns all positional arguments.
Definition: ArgParser.hpp:143
void M_EXPORT execute_file(Diagnostic &diag, const std::filesystem::path &path)
Execute the SQL file at path.
Definition: mutable.cpp:410
std::unique_ptr< ast::Stmt > M_EXPORT statement_from_string(Diagnostic &diag, const std::string &str)
Use lexer, parser, and semantic analysis to create a Stmt from str.
Definition: mutable.cpp:25
void emit_CSG_queries(std::ostream &out, const m::QueryGraph &G, const m::AdjacencyMatrix &M)
void emit_query_slice(std::ostream &out, const m::QueryGraph &G, m::Subproblem slice)
void usage(std::ostream &out, const char *name)
#define ADD(TYPE, VAR, INIT, SHORT, LONG, DESCR, CALLBACK)
bool show_help
‍whether to show a help message
An adjacency matrix for a given query graph.
void for_each_CSG_undirected(SmallBitset super, SmallBitset source, std::function< void(SmallBitset)> callback) const
Enumerate all connected subgraphs (CSGs) of the graph induced by vertex super set super,...
A BaseTable is a DataSource that is materialized and stored persistently by the database system.
Definition: QueryGraph.hpp:89
The catalog contains all Databases and keeps track of all meta information of the database system.
Definition: Catalog.hpp:215
bool has_database_in_use() const
Returns true if any Database is currently in use.
Definition: Catalog.hpp:293
static Catalog & Get()
Return a reference to the single Catalog instance.
static Options & Get()
Return a reference to the single Options instance.
Definition: Options.cpp:9
bool quiet
Definition: Options.hpp:35
The query graph represents all data sources and joins in a graph structure.
Definition: QueryGraph.hpp:172
const auto & joins() const
Definition: QueryGraph.hpp:258
const auto & sources() const
Definition: QueryGraph.hpp:257
static std::unique_ptr< QueryGraph > Build(const ast::Stmt &stmt)
Implements a small and efficient set over integers in the range of 0 to 63 (including).
Definition: ADT.hpp:26
static SmallBitset All(std::size_t n)
Factory method for creating a SmallBitset with first n bits set.
Definition: ADT.hpp:117
auto end() const
Definition: ADT.hpp:175
auto begin() const
Definition: ADT.hpp:173