]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
11fdf7f2 | 3 | |
31f18b77 FG |
4 | #ifndef CEPH_RGW_ES_QUERY_H |
5 | #define CEPH_RGW_ES_QUERY_H | |
6 | ||
7 | #include "rgw_string.h" | |
8 | ||
9 | class ESQueryStack { | |
20effc67 TL |
10 | std::list<std::string> l; |
11 | std::list<std::string>::iterator iter; | |
31f18b77 FG |
12 | |
13 | public: | |
20effc67 | 14 | explicit ESQueryStack(std::list<std::string>& src) { |
31f18b77 FG |
15 | assign(src); |
16 | } | |
17 | ||
18 | ESQueryStack() {} | |
19 | ||
20effc67 | 20 | void assign(std::list<std::string>& src) { |
31f18b77 FG |
21 | l.swap(src); |
22 | iter = l.begin(); | |
23 | } | |
24 | ||
20effc67 | 25 | bool peek(std::string *dest) { |
31f18b77 FG |
26 | if (done()) { |
27 | return false; | |
28 | } | |
29 | *dest = *iter; | |
30 | return true; | |
31 | } | |
32 | ||
20effc67 | 33 | bool pop(std::string *dest) { |
31f18b77 FG |
34 | bool valid = peek(dest); |
35 | if (!valid) { | |
36 | return false; | |
37 | } | |
38 | ++iter; | |
39 | return true; | |
40 | } | |
41 | ||
42 | bool done() { | |
43 | return (iter == l.end()); | |
44 | } | |
45 | }; | |
46 | ||
47 | class ESInfixQueryParser { | |
20effc67 | 48 | std::string query; |
31f18b77 FG |
49 | int size; |
50 | const char *str; | |
51 | int pos{0}; | |
20effc67 | 52 | std::list<std::string> args; |
31f18b77 FG |
53 | |
54 | void skip_whitespace(const char *str, int size, int& pos); | |
55 | bool get_next_token(bool (*filter)(char)); | |
56 | ||
57 | bool parse_condition(); | |
58 | bool parse_and_or(); | |
59 | bool parse_specific_char(const char *pchar); | |
60 | bool parse_open_bracket(); | |
61 | bool parse_close_bracket(); | |
62 | ||
63 | public: | |
20effc67 TL |
64 | explicit ESInfixQueryParser(const std::string& _query) : query(_query), size(query.size()), str(query.c_str()) {} |
65 | bool parse(std::list<std::string> *result); | |
31f18b77 FG |
66 | }; |
67 | ||
68 | class ESQueryNode; | |
69 | ||
70 | struct ESEntityTypeMap { | |
71 | enum EntityType { | |
72 | ES_ENTITY_NONE = 0, | |
73 | ES_ENTITY_STR = 1, | |
74 | ES_ENTITY_INT = 2, | |
75 | ES_ENTITY_DATE = 3, | |
76 | }; | |
77 | ||
20effc67 | 78 | std::map<std::string, EntityType> m; |
31f18b77 | 79 | |
20effc67 | 80 | explicit ESEntityTypeMap(std::map<std::string, EntityType>& _m) : m(_m) {} |
31f18b77 | 81 | |
20effc67 | 82 | bool find(const std::string& entity, EntityType *ptype) { |
31f18b77 FG |
83 | auto i = m.find(entity); |
84 | if (i != m.end()) { | |
85 | *ptype = i->second; | |
86 | return true; | |
87 | } | |
88 | ||
89 | *ptype = ES_ENTITY_NONE; | |
90 | return false; | |
91 | } | |
92 | }; | |
93 | ||
94 | class ESQueryCompiler { | |
95 | ESInfixQueryParser parser; | |
96 | ESQueryStack stack; | |
97 | ESQueryNode *query_root{nullptr}; | |
98 | ||
20effc67 | 99 | std::string custom_prefix; |
31f18b77 | 100 | |
20effc67 | 101 | bool convert(std::list<std::string>& infix, std::string *perr); |
31f18b77 | 102 | |
20effc67 | 103 | std::list<std::pair<std::string, std::string> > eq_conds; |
31f18b77 FG |
104 | |
105 | ESEntityTypeMap *generic_type_map{nullptr}; | |
106 | ESEntityTypeMap *custom_type_map{nullptr}; | |
107 | ||
20effc67 TL |
108 | std::map<std::string, std::string, ltstr_nocase> *field_aliases = nullptr; |
109 | std::set<std::string> *restricted_fields = nullptr; | |
31f18b77 FG |
110 | |
111 | public: | |
20effc67 TL |
112 | ESQueryCompiler(const std::string& query, |
113 | std::list<std::pair<std::string, std::string> > *prepend_eq_conds, | |
114 | const std::string& _custom_prefix) | |
115 | : parser(query), custom_prefix(_custom_prefix) { | |
31f18b77 FG |
116 | if (prepend_eq_conds) { |
117 | eq_conds = std::move(*prepend_eq_conds); | |
118 | } | |
119 | } | |
120 | ~ESQueryCompiler(); | |
121 | ||
20effc67 | 122 | bool compile(std::string *perr); |
31f18b77 FG |
123 | void dump(Formatter *f) const; |
124 | ||
125 | void set_generic_type_map(ESEntityTypeMap *entity_map) { | |
126 | generic_type_map = entity_map; | |
127 | } | |
128 | ||
129 | ESEntityTypeMap *get_generic_type_map() { | |
130 | return generic_type_map; | |
131 | } | |
20effc67 | 132 | const std::string& get_custom_prefix() { return custom_prefix; } |
31f18b77 FG |
133 | |
134 | void set_custom_type_map(ESEntityTypeMap *entity_map) { | |
135 | custom_type_map = entity_map; | |
136 | } | |
137 | ||
138 | ESEntityTypeMap *get_custom_type_map() { | |
139 | return custom_type_map; | |
140 | } | |
141 | ||
20effc67 | 142 | void set_field_aliases(std::map<std::string, std::string, ltstr_nocase> *fa) { |
31f18b77 FG |
143 | field_aliases = fa; |
144 | } | |
145 | ||
20effc67 | 146 | std::string unalias_field(const std::string& field) { |
31f18b77 FG |
147 | if (!field_aliases) { |
148 | return field; | |
149 | } | |
150 | auto i = field_aliases->find(field); | |
151 | if (i == field_aliases->end()) { | |
152 | return field; | |
153 | } | |
154 | ||
155 | return i->second; | |
156 | } | |
157 | ||
20effc67 | 158 | void set_restricted_fields(std::set<std::string> *rf) { |
31f18b77 FG |
159 | restricted_fields = rf; |
160 | } | |
161 | ||
20effc67 | 162 | bool is_restricted(const std::string& f) { |
31f18b77 FG |
163 | return (restricted_fields && restricted_fields->find(f) != restricted_fields->end()); |
164 | } | |
165 | }; | |
166 | ||
167 | ||
168 | #endif |