@@ -1242,6 +1242,7 @@ static int mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data);
1242
1242
static void mdb_cursor_init (MDB_cursor * mc , MDB_txn * txn , MDB_dbi dbi , MDB_xcursor * mx );
1243
1243
static void mdb_xcursor_init0 (MDB_cursor * mc );
1244
1244
static void mdb_xcursor_init1 (MDB_cursor * mc , MDB_node * node );
1245
+ static void mdb_xcursor_init2 (MDB_cursor * mc , MDB_node * node );
1245
1246
1246
1247
static int mdb_drop0 (MDB_cursor * mc , int subs );
1247
1248
static void mdb_default_cmp (MDB_txn * txn , MDB_dbi dbi );
@@ -6554,23 +6555,23 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
6554
6555
rc = mdb_cursor_put (& mc -> mc_xcursor -> mx_cursor , & dkey , & xdata , xflags );
6555
6556
if (rc )
6556
6557
goto bad_sub ;
6557
- {
6558
- /* Adjust other cursors pointing to mp */
6559
- MDB_cursor * m2 ;
6560
- unsigned i = mc -> mc_top ;
6561
- MDB_page * mp = mc -> mc_pg [i ];
6562
-
6563
- for (m2 = mc -> mc_txn -> mt_cursors [mc -> mc_dbi ]; m2 ; m2 = m2 -> mc_next ) {
6564
- if (m2 == mc || m2 -> mc_snum < mc -> mc_snum ) continue ;
6565
- if (!(m2 -> mc_flags & C_INITIALIZED )) continue ;
6566
- if (m2 -> mc_pg [i ] == mp && m2 -> mc_ki [i ] == mc -> mc_ki [i ]) {
6567
- mdb_xcursor_init1 (m2 , leaf );
6568
- }
6569
- }
6570
- }
6571
6558
/* we've done our job */
6572
6559
dkey .mv_size = 0 ;
6573
6560
}
6561
+ {
6562
+ /* Adjust other cursors pointing to mp */
6563
+ MDB_cursor * m2 ;
6564
+ unsigned i = mc -> mc_top ;
6565
+ MDB_page * mp = mc -> mc_pg [i ];
6566
+
6567
+ for (m2 = mc -> mc_txn -> mt_cursors [mc -> mc_dbi ]; m2 ; m2 = m2 -> mc_next ) {
6568
+ if (m2 == mc || m2 -> mc_snum < mc -> mc_snum ) continue ;
6569
+ if (!(m2 -> mc_flags & C_INITIALIZED )) continue ;
6570
+ if (m2 -> mc_pg [i ] == mp && m2 -> mc_ki [i ] == mc -> mc_ki [i ]) {
6571
+ mdb_xcursor_init2 (m2 , leaf );
6572
+ }
6573
+ }
6574
+ }
6574
6575
ecount = mc -> mc_xcursor -> mx_db .md_entries ;
6575
6576
if (flags & MDB_APPENDDUP )
6576
6577
xflags |= MDB_APPEND ;
@@ -7122,6 +7123,54 @@ mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node)
7122
7123
#endif
7123
7124
}
7124
7125
7126
+
7127
+ /** Fixup a sorted-dups cursor due to underlying update.
7128
+ * Sets up some fields that depend on the data from the main cursor.
7129
+ * Almost the same as init1, but skips initialization steps if the
7130
+ * xcursor had already been used.
7131
+ * @param[in] mc The main cursor whose sorted-dups cursor is to be fixed up.
7132
+ * @param[in] node The data containing the #MDB_db record for the
7133
+ * sorted-dup database.
7134
+ */
7135
+ static void
7136
+ mdb_xcursor_init2 (MDB_cursor * mc , MDB_node * node )
7137
+ {
7138
+ MDB_xcursor * mx = mc -> mc_xcursor ;
7139
+
7140
+ if (node -> mn_flags & F_SUBDATA ) {
7141
+ memcpy (& mx -> mx_db , NODEDATA (node ), sizeof (MDB_db ));
7142
+ mdb_page_get (mc -> mc_txn ,mx -> mx_db .md_root ,& mx -> mx_cursor .mc_pg [0 ],NULL );
7143
+ } else {
7144
+ MDB_page * fp = NODEDATA (node );
7145
+ mx -> mx_db .md_entries = NUMKEYS (fp );
7146
+ COPY_PGNO (mx -> mx_db .md_root , fp -> mp_pgno );
7147
+ mx -> mx_cursor .mc_pg [0 ] = fp ;
7148
+ }
7149
+ if (!(mx -> mx_cursor .mc_flags & C_INITIALIZED )) {
7150
+ mx -> mx_cursor .mc_snum = 1 ;
7151
+ mx -> mx_cursor .mc_top = 0 ;
7152
+ mx -> mx_cursor .mc_flags |= C_INITIALIZED ;
7153
+ mx -> mx_cursor .mc_ki [0 ] = 0 ;
7154
+ if (!(node -> mn_flags & F_SUBDATA )) {
7155
+ mx -> mx_db .md_pad = 0 ;
7156
+ mx -> mx_db .md_flags = 0 ;
7157
+ mx -> mx_db .md_depth = 1 ;
7158
+ mx -> mx_db .md_branch_pages = 0 ;
7159
+ mx -> mx_db .md_leaf_pages = 1 ;
7160
+ mx -> mx_db .md_overflow_pages = 0 ;
7161
+ if (mc -> mc_db -> md_flags & MDB_DUPFIXED ) {
7162
+ mx -> mx_db .md_flags = MDB_DUPFIXED ;
7163
+ mx -> mx_db .md_pad = mx -> mx_cursor .mc_pg [0 ]-> mp_pad ;
7164
+ if (mc -> mc_db -> md_flags & MDB_INTEGERDUP )
7165
+ mx -> mx_db .md_flags |= MDB_INTEGERKEY ;
7166
+ }
7167
+ }
7168
+ }
7169
+ DPRINTF (("Sub-db -%u root page %" Z "u" , mx -> mx_cursor .mc_dbi ,
7170
+ mx -> mx_db .md_root ));
7171
+ mx -> mx_dbflag = DB_VALID |DB_USRVALID |DB_DIRTY ; /* DB_DIRTY guides mdb_cursor_touch */
7172
+ }
7173
+
7125
7174
/** Initialize a cursor for a given transaction and database. */
7126
7175
static void
7127
7176
mdb_cursor_init (MDB_cursor * mc , MDB_txn * txn , MDB_dbi dbi , MDB_xcursor * mx )
0 commit comments