1 /* 2 Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License, version 2.0, 6 as published by the Free Software Foundation. 7 8 This program is also distributed with certain software (including 9 but not limited to OpenSSL) that is licensed under separate terms, 10 as designated in a particular file or component or in included license 11 documentation. The authors of MySQL hereby grant you an additional 12 permission to link the program and your derivative works with the 13 separately licensed software that they have included with MySQL. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License, version 2.0, for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25 #ifndef HUGO_QUERY_BUILDER_HPP 26 #define HUGO_QUERY_BUILDER_HPP 27 28 #include <NDBT.hpp> 29 #include <Vector.hpp> 30 #include "../../src/ndbapi/NdbQueryBuilder.hpp" 31 32 class HugoQueryBuilder { 33 public: 34 35 typedef Uint64 OptionMask; 36 37 /** 38 * Options that affects what kind of query is built 39 */ 40 enum QueryOption 41 { 42 /** 43 * Query should be a lookup 44 */ 45 O_LOOKUP = 0x1, 46 47 /** 48 * Query should be a scan 49 */ 50 O_SCAN = 0x2, 51 52 /** 53 * Query might use primary key index 54 */ 55 O_PK_INDEX = 0x4, 56 57 /** 58 * Query might use unique index 59 */ 60 O_UNIQUE_INDEX = 0x8, 61 62 /** 63 * Query might use ordered index 64 */ 65 O_ORDERED_INDEX = 0x10, 66 67 /** 68 * Query might table scan 69 */ 70 O_TABLE_SCAN = 0x20, 71 72 /** 73 * Column referrences may also include grandparents (Default 'on') 74 */ 75 O_GRANDPARENT = 0x100 76 }; 77 static const OptionMask OM_RANDOM_OPTIONS = 78 (OptionMask)(O_PK_INDEX | O_UNIQUE_INDEX | O_ORDERED_INDEX | O_TABLE_SCAN | O_GRANDPARENT); 79 HugoQueryBuilder(Ndb * ndb,const NdbDictionary::Table ** tabptr,OptionMask om=OM_RANDOM_OPTIONS)80 HugoQueryBuilder(Ndb* ndb, const NdbDictionary::Table**tabptr, 81 OptionMask om = OM_RANDOM_OPTIONS) 82 : m_ndb(ndb) 83 { 84 init(); 85 for (; * tabptr != 0; tabptr++) 86 addTable(*tabptr); 87 setOptionMask(om); 88 fixOptions(); 89 } HugoQueryBuilder(Ndb * ndb,const NdbDictionary::Table * tab,QueryOption o)90 HugoQueryBuilder(Ndb* ndb, const NdbDictionary::Table* tab, QueryOption o) 91 : m_ndb(ndb) 92 { 93 init(); 94 addTable(tab); 95 setOption(o); 96 fixOptions(); 97 } 98 virtual ~HugoQueryBuilder(); 99 setMinJoinLevel(int level)100 void setMinJoinLevel(int level) { m_joinLevel[0] = level;} getMinJoinLevel() const101 int getMinJoinLevel() const { return m_joinLevel[0];} setMaxJoinLevel(int level)102 void setMaxJoinLevel(int level) { m_joinLevel[1] = level;} getMaxJoinLevel() const103 int getMaxJoinLevel() const { return m_joinLevel[1];} 104 setJoinLevel(int level)105 void setJoinLevel(int level) { setMinJoinLevel(level);setMaxJoinLevel(level);} 106 int getJoinLevel() const; 107 108 void addTable(const NdbDictionary::Table*); 109 void removeTable(const NdbDictionary::Table*); 110 setOption(QueryOption o)111 void setOption(QueryOption o) { m_options |= (OptionMask)o;} clearOption(QueryOption o) const112 void clearOption(QueryOption o) const { m_options &= ~(OptionMask)o;} testOption(QueryOption o) const113 bool testOption(QueryOption o) const { return (m_options & o) != 0;} 114 getOptionMask() const115 OptionMask getOptionMask() const { return m_options;} setOptionMask(OptionMask om)116 void setOptionMask(OptionMask om) { m_options = om;} 117 118 const NdbQueryDef * createQuery(bool takeOwnership = false); 119 120 private: 121 const Ndb* m_ndb; 122 123 struct TableDef 124 { 125 const NdbDictionary::Table * m_table; 126 Vector<const NdbDictionary::Index*> m_unique_indexes; 127 Vector<const NdbDictionary::Index*> m_ordered_indexes; 128 }; 129 130 void init(); 131 mutable OptionMask m_options; 132 int m_joinLevel[2]; // min/max 133 Vector<TableDef> m_tables; 134 Vector<const NdbQueryDef*> m_queries; 135 136 // get random table 137 struct TableDef getTable() const; 138 139 struct OpIdx 140 { 141 NdbQueryOperationDef::Type m_type; 142 const NdbDictionary::Table * m_table; 143 const NdbDictionary::Index * m_index; 144 }; 145 OpIdx getOp() const; 146 147 struct Op 148 { 149 int m_parent; 150 int m_idx; 151 const NdbQueryOperationDef * m_op; 152 }; 153 154 Vector<Op> m_query; // Query built sofar 155 156 /** 157 * Check if all column in cols can be bound to a column in tables in 158 * ops 159 */ 160 static bool checkBindable(Vector<const NdbDictionary::Column*> cols, 161 Vector<Op> ops, 162 bool allow_bind_nullable); 163 164 Vector<Op> getParents(OpIdx); // 165 NdbQueryOperand * createLink(NdbQueryBuilder&, const NdbDictionary::Column*, 166 Vector<Op> & parents, 167 bool allow_bind_nullable); 168 const NdbQueryOperationDef* createOp(NdbQueryBuilder&); 169 170 void fixOptions(); 171 172 /** 173 * We currently don't support busy-scan joins 174 */ 175 bool checkBusyScan(Op) const; 176 bool isAncestor(const Op& parent, const Op& child) const; 177 178 friend NdbOut& operator<<(NdbOut& out, const HugoQueryBuilder::Op& op); 179 }; 180 181 #endif 182