@@ -2294,6 +2294,110 @@ btr_page_tuple_smaller(
2294
2294
return (cmp_dtuple_rec (tuple, first_rec, *offsets) < 0 );
2295
2295
}
2296
2296
2297
+ /* * Insert the tuple into the right sibling page, if the cursor is at the end
2298
+ of a page.
2299
+ @param[in] flags undo logging and locking flags
2300
+ @param[in,out] cursor cursor at which to insert; when the function succeeds,
2301
+ the cursor is positioned before the insert point.
2302
+ @param[out] offsets offsets on inserted record
2303
+ @param[in,out] heap memory heap for allocating offsets
2304
+ @param[in] tuple tuple to insert
2305
+ @param[in] n_ext number of externally stored columns
2306
+ @param[in,out] mtr mini-transaction
2307
+ @return inserted record (first record on the right sibling page);
2308
+ the cursor will be positioned on the page infimum
2309
+ @retval NULL if the operation was not performed */
2310
+ static
2311
+ rec_t *
2312
+ btr_insert_into_right_sibling (
2313
+ ulint flags,
2314
+ btr_cur_t * cursor,
2315
+ ulint** offsets,
2316
+ mem_heap_t ** heap,
2317
+ const dtuple_t * tuple,
2318
+ ulint n_ext,
2319
+ mtr_t * mtr)
2320
+ {
2321
+ buf_block_t * block = btr_cur_get_block (cursor);
2322
+ page_t * page = buf_block_get_frame (block);
2323
+ ulint next_page_no = btr_page_get_next (page, mtr);
2324
+
2325
+ ut_ad (mtr_memo_contains_flagged (mtr,
2326
+ dict_index_get_lock (cursor->index ),
2327
+ MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)
2328
+ || dict_table_is_intrinsic (cursor->index ->table ));
2329
+ ut_ad (mtr_is_block_fix (
2330
+ mtr, block, MTR_MEMO_PAGE_X_FIX, cursor->index ->table ));
2331
+ ut_ad (*heap);
2332
+
2333
+ if (next_page_no == FIL_NULL || !page_rec_is_supremum (
2334
+ page_rec_get_next (btr_cur_get_rec (cursor)))) {
2335
+
2336
+ return (NULL );
2337
+ }
2338
+
2339
+ page_cur_t next_page_cursor;
2340
+ buf_block_t * next_block;
2341
+ page_t * next_page;
2342
+ btr_cur_t next_father_cursor;
2343
+ rec_t * rec = NULL ;
2344
+
2345
+ const ulint space = block->page .id .space ();
2346
+
2347
+ next_block = btr_block_get (
2348
+ page_id_t (space, next_page_no), block->page .size ,
2349
+ RW_X_LATCH, cursor->index , mtr);
2350
+ next_page = buf_block_get_frame (next_block);
2351
+
2352
+ btr_page_get_father (
2353
+ cursor->index , next_block, mtr, &next_father_cursor);
2354
+
2355
+ page_cur_search (
2356
+ next_block, cursor->index , tuple, PAGE_CUR_LE,
2357
+ &next_page_cursor);
2358
+
2359
+ rec = page_cur_tuple_insert (
2360
+ &next_page_cursor, tuple, cursor->index , offsets, heap,
2361
+ n_ext, mtr);
2362
+
2363
+ if (rec == NULL ) {
2364
+ return (NULL );
2365
+ }
2366
+
2367
+ ibool compressed;
2368
+ dberr_t err;
2369
+ ulint level = btr_page_get_level (next_page, mtr);
2370
+
2371
+ /* adjust cursor position */
2372
+ *btr_cur_get_page_cur (cursor) = next_page_cursor;
2373
+
2374
+ ut_ad (btr_cur_get_rec (cursor) == page_get_infimum_rec (next_page));
2375
+ ut_ad (page_rec_get_next (page_get_infimum_rec (next_page)) == rec);
2376
+
2377
+ /* We have to change the parent node pointer */
2378
+
2379
+ compressed = btr_cur_pessimistic_delete (
2380
+ &err, TRUE , &next_father_cursor,
2381
+ BTR_CREATE_FLAG, false , mtr);
2382
+
2383
+ ut_a (err == DB_SUCCESS);
2384
+
2385
+ if (!compressed) {
2386
+ btr_cur_compress_if_useful (&next_father_cursor, FALSE , mtr);
2387
+ }
2388
+
2389
+ dtuple_t * node_ptr = dict_index_build_node_ptr (
2390
+ cursor->index , rec, next_block->page .id .page_no (),
2391
+ *heap, level);
2392
+
2393
+ btr_insert_on_non_leaf_level (
2394
+ flags, cursor->index , level + 1 , node_ptr, mtr);
2395
+
2396
+ ut_ad (rec_offs_validate (rec, cursor->index , *offsets));
2397
+
2398
+ return (rec);
2399
+ }
2400
+
2297
2401
/* ************************************************************/ /* *
2298
2402
Splits an index page to halves and inserts the tuple. It is assumed
2299
2403
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
@@ -2378,6 +2482,14 @@ btr_page_split_and_insert(
2378
2482
mtr, block, MTR_MEMO_PAGE_X_FIX, cursor->index ->table ));
2379
2483
ut_ad (!page_is_empty (page));
2380
2484
2485
+ /* try to insert to the next page if possible before split */
2486
+ rec = btr_insert_into_right_sibling (
2487
+ flags, cursor, offsets, heap, tuple, n_ext, mtr);
2488
+
2489
+ if (rec != NULL ) {
2490
+ return (rec);
2491
+ }
2492
+
2381
2493
page_no = block->page .id .page_no ();
2382
2494
2383
2495
/* 1. Decide the split record; split_rec == NULL means that the
0 commit comments