1 #ifndef SQL_HASH_JOIN_CHUNK_H_
2 #define SQL_HASH_JOIN_CHUNK_H_
3 
4 /* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License, version 2.0,
8    as published by the Free Software Foundation.
9 
10    This program is also distributed with certain software (including
11    but not limited to OpenSSL) that is licensed under separate terms,
12    as designated in a particular file or component or in included license
13    documentation.  The authors of MySQL hereby grant you an additional
14    permission to link the program and your derivative works with the
15    separately licensed software that they have included with MySQL.
16 
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License, version 2.0, for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
25 
26 #include <stddef.h>
27 
28 #include "my_alloc.h"
29 #include "my_base.h"
30 #include "my_inttypes.h"
31 #include "my_sys.h"
32 #include "sql/hash_join_buffer.h"
33 
34 class String;
35 
36 // A HashJoinChunk is a file located on disk that can be used to store rows.
37 // It is used in on-disk hash join when a table is to be partitioned out to
38 // several smaller files, a.k.a. HashJoinChunks.
39 //
40 // When writing a column to a HashJoinChunk, we use StoreFromTableBuffers for
41 // converting the necessary columns into a format suitable for storage on disk.
42 // Conveniently, StoreFromTableBuffers creates a contiguous range of bytes and a
43 // corresponding length that easily and efficiently can be written out to the
44 // file. When reading rows back from a file, LoadIntoTableBuffers() is used to
45 // put the row back into the table record buffers.
46 //
47 // The basic usage goes like this:
48 //
49 //   HashJoinChunk chunk;
50 //   // Initialize a chunk to hold data from the given tables without any match
51 //   // flags.
52 //   chunk.Init(tables, /*uses_match_flags=*/false);
53 //   String buffer; // A buffer that is used when copying data between tables
54 //                  // and the chunk file, and vica versa.
55 //   while (iterator->Read() == 0) {
56 //     // Write the row that lies in the record buffers of "tables" to this
57 //     // chunk, using the provided buffer. If the chunk file was initialized to
58 //     // use match flags, we would prefix the row with a match flag saying that
59 //     // this row did not have any matching row.
60 //     chunk.WriteRowToChunk(&buffer, /*matched=*/false);
61 //   };
62 //
63 //   chunk.Rewind(); // Prepare to read the first row in this chunk.
64 //
65 //   bool match_flag,
66 //   // Put the row from the chunk to the record buffers of "tables", using the
67 //   // provided buffer. If the chunk file was initialized to use match flags,
68 //   // the match flag for the row read would be stored in 'match_flag'.
69 //   chunk.LoadRowFromChunk(&buffer, &match_flag);
70 class HashJoinChunk {
71  public:
72   HashJoinChunk() = default;  // Constructible.
73 
74   HashJoinChunk(HashJoinChunk &&other);  // Movable.
75 
76   HashJoinChunk(const HashJoinChunk &obj) = delete;
77 
78   HashJoinChunk &operator=(HashJoinChunk &&other);
79 
80   ~HashJoinChunk();
81 
82   /// Initialize this HashJoinChunk.
83   ///
84   /// @param tables The tables to store row data from. Which column we store in
85   ///   the chunk file is determined by each tables read set.
86   /// @param uses_match_flags Whether each row should be prefixed with a match
87   ///   flag, saying whether the row had a matching row.
88   ///
89   /// @returns true if the initialization failed.
90   bool Init(const hash_join_buffer::TableCollection &tables,
91             bool uses_match_flags);
92 
93   /// @returns the number of rows in this HashJoinChunk
num_rows()94   ha_rows num_rows() const { return m_num_rows; }
95 
96   /// Write a row to the HashJoinChunk.
97   ///
98   /// Read the row that lies in the record buffer (record[0]) of the given
99   /// tables and write it out to the underlying file. If the QEP_TAB signals
100   /// that the row ID should be kept, it is also written out. Note that
101   /// TABLE::read_set is used to signal which columns that should be written to
102   /// the chunk.
103   ///
104   /// @param buffer a buffer that is used when copying data from the tables to
105   ///   the chunk file. Note that any existing data in "buffer" is overwritten.
106   /// @param matched whether this row has seen a matching row from the other
107   ///   input. The flag is only written if 'm_uses_match_flags' is set, and if
108   ///   the row comes from the probe input.
109   ///
110   /// @retval true on error.
111   bool WriteRowToChunk(String *buffer, bool matched);
112 
113   /// Read a row from the HashJoinChunk and put it in the record buffer.
114   ///
115   /// The function will read a row from file on disk and put it in the record
116   /// buffers (table->record[0]) in the provided tables. The file on disk should
117   /// already be pointing to the start of a row.
118   ///
119   /// @param buffer a buffer that is used when copying data from the chunk file
120   ///   to the tables. Note that any existing data in "buffer" is overwritten.
121   ///
122   /// @param[out] matched whether this row has seen a matching row from the
123   ///   other input. The flag is only restored if 'm_uses_match_flags' is set,
124   ///   and if the row comes from the probe input.
125   /// @retval true on error.
126   bool LoadRowFromChunk(String *buffer, bool *matched);
127 
128   /// Flush the file buffer, and prepare the file for reading.
129   ///
130   /// @retval true on error
131   bool Rewind();
132 
133  private:
134   // A collection of which tables the chunk file holds data from. Used to
135   // determine where to read data from, and where to put the data back.
136   hash_join_buffer::TableCollection m_tables;
137 
138   // The number of rows in this chunk file.
139   ha_rows m_num_rows{0};
140 
141   // The underlying file that is used when reading data to and from disk.
142   IO_CACHE m_file;
143 
144   // Whether every row is prefixed with a match flag.
145   bool m_uses_match_flags{false};
146 };
147 
148 #endif  // SQL_HASH_JOIN_CHUNK_H_
149