1
+ #include " mysql/plugin.h"
2
+ #include " sql/sql_class.h"
3
+ #include " storage/memem/ha_memem.h"
4
+
5
+ // ------------------------------------------------------
6
+ // Flags
7
+ // ------------------------------------------------------
8
+
9
+ /* *
10
+ * @brief Get the storage engine name
11
+ *
12
+ * Returns the name used to identify this storage engine.
13
+ * This name is used in SHOW TABLE STATUS and SHOW CREATE TABLE.
14
+ *
15
+ * @return const char* Storage engine name
16
+ */
17
+ const char * ha_memem::table_type () const { return " MEMEM" ; }
18
+
19
+ /* *
20
+ * @brief Get table flags that specify handler capabilities
21
+ *
22
+ * Returns a bitmap of flags that tells MySQL about the capabilities
23
+ * of this storage engine. Current flags:
24
+ * - HA_NO_TRANSACTIONS: Engine doesn't support transactions
25
+ * - HA_BINLOG_ROW_CAPABLE: Can handle row-based binary logging
26
+ *
27
+ * @return ulonglong Bitmap of handler flags
28
+ */
29
+ ulonglong ha_memem::table_flags () const {
30
+ return HA_NO_TRANSACTIONS | HA_BINLOG_ROW_CAPABLE;
31
+ }
32
+
33
+ /* *
34
+ * @brief Get index capabilities
35
+ *
36
+ * Returns flags that indicate what kind of indexes this storage engine
37
+ * supports. Returns 0 as this basic implementation doesn't support indexes.
38
+ */
39
+ uLong ha_memem::index_flags (uint, uint, bool ) const { return 0 ; }
40
+
41
+ // ------------------------------------------------------
42
+ // Core
43
+ // ------------------------------------------------------
44
+
45
+ //
46
+ // Called when: CREATE TABLE is executed
47
+ // Purpose: Initialize the table structure/files
48
+ //
49
+ int ha_memem::create (const char * name,
50
+ TABLE* form [[maybe_unused]],
51
+ HA_CREATE_INFO* create_info [[maybe_unused]],
52
+ dd::Table* table_def [[maybe_unused]]) {
53
+ mem_table = new MememTable ();
54
+ mem_table->name = name;
55
+ thr_lock_init (&mem_table->lock ); // Initialize lock
56
+ thr_lock_data_init (&mem_table->lock , &lock, NULL ); // Initialize lock data
57
+ return 0 ;
58
+ }
59
+
60
+ //
61
+ // Called when: Table is opened for operations
62
+ // Purpose: Open existing table for read/write
63
+ //
64
+ int ha_memem::open (const char * name,
65
+ int mode [[maybe_unused]],
66
+ uint test_if_locked [[maybe_unused]],
67
+ const dd::Table* table_def [[maybe_unused]]) {
68
+ mem_table = new MememTable ();
69
+ mem_table->name = name;
70
+ thr_lock_init (&mem_table->lock ); // Initialize lock
71
+ thr_lock_data_init (&mem_table->lock , &lock, NULL ); // Initialize lock data
72
+ return 0 ;
73
+ }
74
+
75
+ int ha_memem::close () {
76
+ if (mem_table) {
77
+ thr_lock_delete (&mem_table->lock ); // Clean up lock
78
+ delete mem_table;
79
+ mem_table = nullptr ;
80
+ }
81
+ return 0 ;
82
+ }
83
+
84
+
85
+ int ha_memem::write_row (uchar* buf) {
86
+ size_t row_length = table->s ->stored_rec_length ;
87
+ mem_table->rows .emplace_back (buf, buf + row_length);
88
+ return 0 ;
89
+ }
90
+
91
+ /* *
92
+ * @brief Initialize table scanning
93
+ *
94
+ * Called before starting a table scan. Initializes position
95
+ * for sequential reading of rows.
96
+ *
97
+ * @param scan True if this is a full table scan
98
+ * @return int 0 for success, non-zero for failure
99
+ */
100
+ int ha_memem::rnd_init (bool scan [[maybe_unused]]) {
101
+ current_position = 0 ;
102
+ return 0 ;
103
+ }
104
+
105
+ /* *
106
+ * @brief Read the next row in a table scan
107
+ *
108
+ * Reads the next row in a sequential scan and places it in
109
+ * the provided buffer.
110
+ *
111
+ * @param buf Buffer to store the row
112
+ * @return int 0 for success, HA_ERR_END_OF_FILE for end of table
113
+ */
114
+ int ha_memem::rnd_next (uchar* buf) {
115
+ if (current_position >= mem_table->rows .size ()) {
116
+ return HA_ERR_END_OF_FILE;
117
+ }
118
+
119
+ memcpy (buf, mem_table->rows [current_position].data (),
120
+ mem_table->rows [current_position].size ());
121
+ current_position++;
122
+ return 0 ;
123
+ }
124
+
125
+ /* *
126
+ * @brief Store position for later retrieval
127
+ *
128
+ * Stores current position for later retrieval by rnd_pos().
129
+ * Used for ORDER BY and GROUP BY operations.
130
+ *
131
+ * @param record Currently unused
132
+ */
133
+ void ha_memem::position (const uchar*) {
134
+ size_t * position = reinterpret_cast <size_t *>(ref);
135
+ *position = current_position - 1 ;
136
+ }
137
+
138
+ /* *
139
+ * @brief Read a row using position
140
+ *
141
+ * Reads a row from a given position. The position information
142
+ * comes from an earlier call to position().
143
+ *
144
+ * @param buf Buffer to store the row
145
+ * @param pos Position information
146
+ * @return int 0 for success, HA_ERR_END_OF_FILE for invalid position
147
+ */
148
+ int ha_memem::rnd_pos (uchar* buf, uchar* pos) {
149
+ size_t position = *reinterpret_cast <size_t *>(pos);
150
+ if (position >= mem_table->rows .size ()) {
151
+ return HA_ERR_END_OF_FILE;
152
+ }
153
+
154
+ memcpy (buf, mem_table->rows [position].data (),
155
+ mem_table->rows [position].size ());
156
+ return 0 ;
157
+ }
158
+
159
+
160
+ /* *
161
+ * @brief Information about the table
162
+ *
163
+ * Called to get information about the table. Currently a no-op
164
+ * in this basic implementation.
165
+ *
166
+ * @param flag Type of information requested
167
+ * @return int 0 for success
168
+ */
169
+ int ha_memem::info (uint) { return 0 ; }
170
+
171
+ // ------------------------------------------------------
172
+ // Locks
173
+ // ------------------------------------------------------
174
+
175
+ /* *
176
+ * @brief External table lock handler
177
+ *
178
+ * This function is called by MySQL at the beginning and end of every statement that
179
+ * references this table. It manages external/file-level locks for the table.
180
+ *
181
+ * Called twice for each statement:
182
+ * 1. At start with lock_type = F_RDLCK (read) or F_WRLCK (write)
183
+ * 2. At end with lock_type = F_UNLCK
184
+ *
185
+ * For transactional tables, this should be a no-op as transactions
186
+ * handle the locking automatically.
187
+ *
188
+ * @param thd Thread handler (unused in basic implementation)
189
+ * @param lock_type Type of lock (F_RDLCK, F_WRLCK, F_UNLCK)
190
+ * @return 0 for success, non-zero for failure
191
+ */
192
+ int ha_memem::external_lock (THD* thd [[maybe_unused]], int lock_type [[maybe_unused]]) {
193
+ DBUG_TRACE;
194
+ return 0 ;
195
+ }
196
+
197
+ /* *
198
+ * @brief Store lock request in lock structure
199
+ *
200
+ * This method is called by MySQL to build a list of table-level locks needed
201
+ * for a particular statement. It's called multiple times to build the complete
202
+ * lock list before actually trying to acquire the locks.
203
+ *
204
+ * Lock upgrade protocol:
205
+ * - If lock_type is TL_IGNORE, keep existing lock type
206
+ * - If current lock is TL_UNLOCK, set to requested lock_type
207
+ * - Otherwise, keep existing lock type (don't downgrade)
208
+ *
209
+ * Common lock types:
210
+ * - TL_READ: Normal read lock
211
+ * - TL_READ_WITH_SHARED_LOCKS: READ with LOCK IN SHARE MODE
212
+ * - TL_WRITE: Normal write lock
213
+ * - TL_WRITE_ALLOW_WRITE: INSERT operations
214
+ *
215
+ * @param thd Thread handler
216
+ * @param to Pointer to an array of lock requests
217
+ * @param lock_type Type of lock requested
218
+ * @return Position after the current lock in the lock array
219
+ */
220
+ THR_LOCK_DATA** ha_memem::store_lock (THD* thd [[maybe_unused]],
221
+ THR_LOCK_DATA** to,
222
+ enum thr_lock_type lock_type) {
223
+ // Only change lock type if:
224
+ // 1. Lock type is not TL_IGNORE
225
+ // 2. Current lock type is TL_UNLOCK (no lock)
226
+ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
227
+ lock.type = lock_type;
228
+ }
229
+
230
+ // Add this lock to the table's lock list
231
+ *to++ = &lock;
232
+
233
+ // Return position after our lock
234
+ return to;
235
+ }
236
+
237
+ // --------------------------------------------------
238
+ // Plugin-specific declarations and definitions
239
+ // --------------------------------------------------
240
+
241
+ /* *
242
+ * @brief Create handler instance for the storage engine
243
+ *
244
+ * Called by MySQL to create a new handler instance when a table is opened.
245
+ * Uses placement new to create the handler in the provided memory root.
246
+ *
247
+ * @param hton Handlerton for this storage engine
248
+ * @param table TABLE_SHARE containing table definition
249
+ * @param partitioned Whether table is partitioned (unused in basic implementation)
250
+ * @param mem_root Memory root to allocate handler from
251
+ * @return handler* Pointer to newly created handler instance
252
+ */
253
+ static handler* memem_create_handler (handlerton* hton,
254
+ TABLE_SHARE* table,
255
+ bool ,
256
+ MEM_ROOT* mem_root) {
257
+ return new (mem_root) ha_memem (hton, table);
258
+ }
259
+
260
+ ha_memem::ha_memem (handlerton* hton, TABLE_SHARE* table_arg)
261
+ : handler(hton, table_arg), mem_table(nullptr ), current_position(0 ) {}
262
+
263
+ ha_memem::~ha_memem () = default ;
264
+
265
+ /* * Global handlerton instance for the MEMEM storage engine */
266
+ handlerton *memem_hton;
267
+
268
+ /* *
269
+ * @brief Initialize the storage engine plugin
270
+ *
271
+ * Called when the storage engine is loaded. Initializes the handlerton
272
+ * with the necessary function pointers and capabilities.
273
+ */
274
+ static int memem_init_func (void * p) {
275
+ memem_hton = (handlerton *)p;
276
+ memem_hton->state = SHOW_OPTION_YES; // Mark plugin as active
277
+ memem_hton->create = memem_create_handler; // Set handler creation function
278
+ memem_hton->flags = HTON_CAN_RECREATE; // Set capabilities
279
+ return 0 ;
280
+ }
281
+
282
+ static int memem_deinit_func (void * p [[maybe_unused]]) {
283
+ return 0 ;
284
+ }
285
+
286
+ /* *
287
+ * @brief Storage engine descriptor
288
+ *
289
+ * Contains version information for the storage engine interface.
290
+ * Used by MySQL to verify compatibility.
291
+ */
292
+ static struct st_mysql_storage_engine memem_storage_engine = {
293
+ MYSQL_HANDLERTON_INTERFACE_VERSION
294
+ };
295
+
296
+ /* *
297
+ * @brief Plugin declaration structure
298
+ *
299
+ * Declares the storage engine plugin to MySQL, including:
300
+ * - Plugin type (storage engine)
301
+ * - Name and author information
302
+ * - License information
303
+ * - Initialize and cleanup functions
304
+ * - Version and status information
305
+ */
306
+ mysql_declare_plugin (memem) {
307
+ MYSQL_STORAGE_ENGINE_PLUGIN,
308
+ &memem_storage_engine, // Plugin descriptor
309
+ " MEMEM" , // Plugin name
310
+ PLUGIN_AUTHOR_ORACLE, // Author
311
+ " MEMEM storage engine" , // Description
312
+ PLUGIN_LICENSE_GPL, // License
313
+ memem_init_func, // Initialization function
314
+ nullptr , // Check uninstall function
315
+ memem_deinit_func, // Cleanup function
316
+ 0x0001 , // Version number (0.1)
317
+ nullptr , // Status variables
318
+ nullptr , // System variables
319
+ nullptr , // Config options
320
+ 0 , // Flags
321
+ }
322
+ mysql_declare_plugin_end;
0 commit comments