1 /* 2 Copyright (c) 2011, 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 * If not any options set, random query qill be created 74 */ 75 O_RANDOM_OPTIONS = (OptionMask)((~(OptionMask)0) & 76 ~(OptionMask)(O_SCAN | O_LOOKUP)) 77 }; 78 static const OptionMask OM_RANDOM_OPTIONS = (OptionMask)O_RANDOM_OPTIONS; 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 init(); 83 for (; * tabptr != 0; tabptr++) 84 addTable(ndb, * tabptr); 85 setOptionMask(om); 86 fixOptions(); 87 } HugoQueryBuilder(Ndb * ndb,const NdbDictionary::Table * tab,QueryOption o)88 HugoQueryBuilder(Ndb* ndb, const NdbDictionary::Table* tab, QueryOption o) { 89 init(); 90 addTable(ndb, tab); 91 setOption(o); 92 fixOptions(); 93 } 94 virtual ~HugoQueryBuilder(); 95 setMinJoinLevel(int level)96 void setMinJoinLevel(int level) { m_joinLevel[0] = level;} getMinJoinLevel() const97 int getMinJoinLevel() const { return m_joinLevel[0];} setMaxJoinLevel(int level)98 void setMaxJoinLevel(int level) { m_joinLevel[1] = level;} getMaxJoinLevel() const99 int getMaxJoinLevel() const { return m_joinLevel[1];} 100 setJoinLevel(int level)101 void setJoinLevel(int level) { setMinJoinLevel(level);setMaxJoinLevel(level);} 102 int getJoinLevel() const; 103 104 void addTable(Ndb*, const NdbDictionary::Table*); 105 void removeTable(const NdbDictionary::Table*); 106 setOption(QueryOption o)107 void setOption(QueryOption o) { m_options |= (OptionMask)o;} clearOption(QueryOption o) const108 void clearOption(QueryOption o) const { m_options &= ~(OptionMask)o;} testOption(QueryOption o) const109 bool testOption(QueryOption o) const { return (m_options & o) != 0;} 110 getOptionMask() const111 OptionMask getOptionMask() const { return m_options;} setOptionMask(OptionMask om)112 void setOptionMask(OptionMask om) { m_options = om;} 113 114 const NdbQueryDef * createQuery(bool takeOwnership = false); 115 116 private: 117 struct TableDef 118 { 119 const NdbDictionary::Table * m_table; 120 Vector<const NdbDictionary::Index*> m_unique_indexes; 121 Vector<const NdbDictionary::Index*> m_ordered_indexes; 122 }; 123 124 void init(); 125 mutable OptionMask m_options; 126 int m_joinLevel[2]; // min/max 127 Vector<TableDef> m_tables; 128 Vector<const NdbQueryDef*> m_queries; 129 130 // get random table 131 struct TableDef getTable() const; 132 133 struct OpIdx 134 { 135 NdbQueryOperationDef::Type m_type; 136 const NdbDictionary::Table * m_table; 137 const NdbDictionary::Index * m_index; 138 }; 139 OpIdx getOp() const; 140 141 struct Op 142 { 143 int m_parent; 144 int m_idx; 145 const NdbQueryOperationDef * m_op; 146 }; 147 148 Vector<Op> m_query; // Query built sofar 149 150 /** 151 * Check if all column in cols can be bound to a column in tables in 152 * ops 153 */ 154 static bool checkBindable(Vector<const NdbDictionary::Column*> cols, 155 Vector<Op> ops, 156 bool allow_bind_nullable); 157 158 Vector<Op> getParents(OpIdx); // 159 NdbQueryOperand * createLink(NdbQueryBuilder&, const NdbDictionary::Column*, 160 Vector<Op> & parents, 161 bool allow_bind_nullable); 162 const NdbQueryOperationDef* createOp(NdbQueryBuilder&); 163 164 void fixOptions(); 165 166 /** 167 * We currently don't support busy-scan joins 168 */ 169 bool checkBusyScan(Op) const; 170 bool isAncestor(const Op& parent, const Op& child) const; 171 172 friend NdbOut& operator<<(NdbOut& out, const HugoQueryBuilder::Op& op); 173 }; 174 175 #endif 176