1 /* Copyright (c) 2014, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
22 
23 #ifndef FAKE_RANGE_OPT_PARAM
24 #define FAKE_RANGE_OPT_PARAM
25 
26 
27 #include <gmock/gmock.h>
28 #include "fake_table.h"
29 
30 #include "opt_range.cc"
31 
32 using ::testing::Return;
33 using ::testing::_;
34 
35 class Fake_RANGE_OPT_PARAM : public RANGE_OPT_PARAM
36 {
37   KEY_PART m_key_parts[64];
38   Mem_root_array<KEY_PART_INFO, true> m_kpis;
39   Fake_TABLE fake_table;
40 
41 public:
42 
43   /**
44     Creates a Fake_RANGE_OPT_PARAM and optionally a Fake_TABLE.
45 
46     @note The Fake_TABLE is always created, but with zero columns if
47     number_columns is zero. However, it won't be used since
48     Fake_RANGE_OPT_PARAM::table is NULL.
49 
50     @param number_columns If non-zero, a Fake_TABLE is created with
51     this many columns.
52 
53     @param columns_nullable Creates nullable columns, if applicable.
54   */
Fake_RANGE_OPT_PARAM(THD * thd_arg,MEM_ROOT * alloc_arg,int number_columns,bool columns_nullable)55   Fake_RANGE_OPT_PARAM(THD *thd_arg, MEM_ROOT *alloc_arg, int number_columns,
56                        bool columns_nullable)
57     : m_kpis(alloc_arg),
58       fake_table(number_columns, columns_nullable)
59   {
60     m_kpis.reserve(64);
61 
62     thd= thd_arg;
63     mem_root= alloc_arg;
64 
65     if (number_columns != 0)
66     {
67       table= &fake_table;
68       current_table= table->pos_in_table_list->map();
69     }
70     else
71     {
72       table= NULL;
73       current_table= 1;
74     }
75 
76     using_real_indexes= true;
77     key_parts= m_key_parts;
78     key_parts_end= m_key_parts;
79     keys= 0;
80     /*
81       Controls whether or not ranges that do not have conditions on
82       the first keypart are removed before two trees are ORed in such
83       a way that index merge is required. The value of 'true' means
84       that such ranges are removed.
85     */
86     remove_jump_scans= true;
87 
88     const Mock_HANDLER *mock_handler= &fake_table.mock_handler;
89 
90     ON_CALL(*mock_handler, index_flags(_, _, true))
91       .WillByDefault(Return(HA_READ_RANGE));
92   }
93 
add_key(List<Field> fields_in_index)94   void add_key(List<Field> fields_in_index)
95   {
96     List_iterator<Field> it(fields_in_index);
97     int cur_kp= 0;
98 
99     table->key_info[keys].actual_key_parts= 0;
100     for (Field *cur_field= it++; cur_field; cur_field= it++, cur_kp++)
101     {
102       KEY_PART_INFO *kpi= m_kpis.end();  // Points past the end.
103       m_kpis.push_back(KEY_PART_INFO()); // kpi now points to a new element
104       kpi->init_from_field(cur_field);
105 
106       key_parts_end->key=          keys;
107       key_parts_end->part=         cur_kp;
108       key_parts_end->length=       kpi->store_length;
109       key_parts_end->store_length= kpi->store_length;
110       key_parts_end->field=        kpi->field;
111       key_parts_end->null_bit=     kpi->null_bit;
112       key_parts_end->flag=         static_cast<uint8>(kpi->key_part_flag);
113       key_parts_end->image_type =  Field::itRAW;
114 
115       key_parts_end++;
116       table->key_info[keys].key_part[cur_kp]= *kpi;
117       table->key_info[keys].actual_key_parts++;
118     }
119     table->key_info[keys].user_defined_key_parts=
120       table->key_info[keys].actual_key_parts;
121     real_keynr[keys]= keys;
122     keys++;
123   }
124 
add_key(Field * field_to_index)125   void add_key(Field *field_to_index)
126   {
127     List<Field> index_list;
128     index_list.push_back(field_to_index);
129     add_key(index_list);
130   }
131 
add_key(Field * field_to_index1,Field * field_to_index2)132   void add_key(Field *field_to_index1, Field *field_to_index2)
133   {
134     List<Field> index_list;
135     index_list.push_back(field_to_index1);
136     index_list.push_back(field_to_index2);
137     add_key(index_list);
138   }
139 
140   /// Creates an index over all columns in the RANGE_OPT_PARAM's table.
add_key()141   void add_key()
142   {
143     List<Field> index_list;
144     for (uint i= 0; i < table->s->fields; ++i)
145       index_list.push_back(table->field[i]);
146     add_key(index_list);
147   }
148 
~Fake_RANGE_OPT_PARAM()149   ~Fake_RANGE_OPT_PARAM()
150   {
151     for (uint i= 0; i < keys; i++)
152     {
153       table->key_info[i].actual_key_parts= 0;
154       table->key_info[i].user_defined_key_parts= 0;
155     }
156   }
157 
158 };
159 
160 #endif // FAKE_RANGE_OPT_PARAM
161