| 5760 | |
| 5761 | |
| 5762 | static ULONG insert_node(thread_db* tdbb, |
| 5763 | WIN* window, |
| 5764 | index_insertion* insertion, |
| 5765 | temporary_key* new_key, |
| 5766 | RecordNumber* new_record_number, |
| 5767 | ULONG* original_page, |
| 5768 | ULONG* sibling_page) |
| 5769 | { |
| 5770 | /************************************** |
| 5771 | * |
| 5772 | * i n s e r t _ n o d e |
| 5773 | * |
| 5774 | ************************************** |
| 5775 | * |
| 5776 | * Functional description |
| 5777 | * Insert a node in a index leaf page. |
| 5778 | * If this isn't the right bucket, return NO_VALUE. |
| 5779 | * If it splits, return the split page number and |
| 5780 | * leading string. This is the workhorse for add_node. |
| 5781 | * |
| 5782 | **************************************/ |
| 5783 | |
| 5784 | SET_TDBB(tdbb); |
| 5785 | const Database* dbb = tdbb->getDatabase(); |
| 5786 | CHECK_DBB(dbb); |
| 5787 | |
| 5788 | const USHORT pageSpaceID = window->win_page.getPageSpaceID(); |
| 5789 | |
| 5790 | // find the insertion point for the specified key |
| 5791 | btree_page* bucket = (btree_page*) window->win_buffer; |
| 5792 | temporary_key* key = insertion->iib_key; |
| 5793 | |
| 5794 | const index_desc* const idx = insertion->iib_descriptor; |
| 5795 | const bool unique = (idx->idx_flags & idx_unique); |
| 5796 | const bool primary = (idx->idx_flags & idx_primary); |
| 5797 | const bool key_all_nulls = (key->key_nulls == (1 << idx->idx_count) - 1); |
| 5798 | const bool leafPage = (bucket->btr_level == 0); |
| 5799 | // hvlad: don't check unique index if key has only null values |
| 5800 | const bool validateDuplicates = (unique && !key_all_nulls) || primary; |
| 5801 | |
| 5802 | USHORT prefix = 0; |
| 5803 | const RecordNumber newRecordNumber = leafPage ? |
| 5804 | insertion->iib_number : *new_record_number; |
| 5805 | |
| 5806 | // For checking on duplicate nodes we should find the first matching key. |
| 5807 | UCHAR* pointer = find_node_start_point(bucket, key, 0, &prefix, |
| 5808 | idx->idx_flags & idx_descending, |
| 5809 | false, true, validateDuplicates ? NO_VALUE : newRecordNumber); |
| 5810 | if (!pointer) |
| 5811 | return NO_VALUE_PAGE; |
| 5812 | |
| 5813 | if ((UCHAR*) pointer - (UCHAR*) bucket > dbb->dbb_page_size) |
| 5814 | BUGCHECK(205); // msg 205 index bucket overfilled |
| 5815 | |
| 5816 | IndexNode beforeInsertNode; |
| 5817 | pointer = beforeInsertNode.readNode(pointer, leafPage); |
| 5818 | |
| 5819 | // loop through the equivalent nodes until the correct insertion |
no test coverage detected