-
Notifications
You must be signed in to change notification settings - Fork 4k
/
Copy pathquery_builder.h
148 lines (118 loc) · 4.88 KB
/
query_builder.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#ifndef QUERY_BUILDER_INCLUDED
#define QUERY_BUILDER_INCLUDED
/* Copyright (c) 2015, 2024, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
as published by the Free Software Foundation.
This program is designed to work with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have either included with
the program or referenced in the documentation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License, version 2.0, for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "my_config.h"
#include <string>
#include <vector>
#include "plugin/rewriter/rule.h"
#include "plugin/rewriter/services.h"
/**
@file query_builder.h
*/
/**
Class that builds the rewritten query by appending literals in the order
they appear in the parse tree.
*/
class Query_builder : public services::Literal_visitor {
public:
Query_builder(const Pattern *pattern, const Replacement *replacement)
: m_previous_slot(0),
m_replacement(replacement->query_string),
m_slots(replacement->slots()),
m_slots_iter(m_slots.begin()),
m_pattern_literals(pattern->literals),
m_pattern_literals_iter(m_pattern_literals.begin()),
m_matches_so_far(true) {}
/**
Implementation of the visit() function that bridges to add_next_literal().
@param item The current literal.
*/
bool visit(MYSQL_ITEM item) override { return add_next_literal(item); }
/**
To be called after visit() has been called for all literals in the parse
tree that this Query_builder was visiting. This function finishes the
string to yield a complete query.
*/
const std::string &get_built_query() {
// Append trailing segment of replacement.
m_built_query += m_replacement.substr(m_previous_slot);
return m_built_query;
}
/**
Status of the matching of literals that are not parameter markers.
@retval true The parse tree matches the pattern and it is safe to continue
adding literals.
@retval false Some literal has been found to differ between parse tree and
pattern. Execution must end immediately.
*/
bool matches() const { return m_matches_so_far; }
private:
/**
The index of the character in 'm_replacement' after the last slot that we
filled.
*/
int m_previous_slot;
/// Query we copy from (replacement string.)
std::string m_replacement;
/// The slots in the replacement string.
std::vector<int> m_slots;
std::vector<int>::iterator m_slots_iter;
/// All literals in the pattern, in order of appearance in parse tree.
std::vector<std::string> m_pattern_literals;
std::vector<std::string>::iterator m_pattern_literals_iter;
/// The query under construction.
std::string m_built_query;
/**
Whether the literals in the parse tree match those of the pattern so
far.
*/
bool m_matches_so_far;
/**
Adds a literal, assumed to be the next in the parse tree, from the query's
parse tree to this Query_builder.
@param item Assumed to be a literal.
@retval true The builder is finished. Either it has been detected that the
current literal does not match the pattern, or no more literals are needed
to build the query.
*/
bool add_next_literal(MYSQL_ITEM item);
};
bool Query_builder::add_next_literal(MYSQL_ITEM item) {
std::string query_literal = services::print_item(item);
std::string pattern_literal = *m_pattern_literals_iter;
if (pattern_literal.compare("?") ==
0) { // Literal corresponds to a parameter marker in the pattern.
if (m_slots_iter != m_slots.end()) // There are more slots to fill
{
// The part of the replacement leading up to its corresponding slot.
m_built_query += m_replacement.substr(m_previous_slot,
*m_slots_iter - m_previous_slot);
m_built_query += query_literal;
m_previous_slot = *m_slots_iter++ + 1;
}
} else if (pattern_literal.compare(query_literal) != 0) {
// The literal does not match the pattern nor a parameter marker, we
// fail to rewrite.
m_matches_so_far = false;
return true;
}
return ++m_pattern_literals_iter == m_pattern_literals.end();
}
#endif // QUERY_BUILDER_INCLUDED