@@ -590,10 +590,16 @@ static int rewriteAncestorSpine(
590590 if ( countDelta < 0 && cnt == 0 ){
591591 rc = SQLITE_CORRUPT ;
592592 }else {
593+ u64 newCnt = cnt ;
594+ if ( countDelta < 0 ){
595+ newCnt -- ;
596+ }else if ( countDelta > 0 ){
597+ newCnt ++ ;
598+ }
593599 prollyNodeKey (pNode , i , & pKey , & nKey );
594600 rc = prollyNodeBuilderAddWithCount (
595601 & b , pKey , nKey , pChildHash -> data , PROLLY_HASH_SIZE ,
596- countDelta < 0 ? cnt - 1 : cnt + 1 );
602+ newCnt );
597603 }
598604 }else {
599605 rc = appendNodeEntryToBuilder (& b , pNode , i , cnt );
@@ -613,12 +619,11 @@ static int rewriteAncestorSpine(
613619 return SQLITE_OK ;
614620}
615621
616- /* Replace one existing row when node boundaries cannot change. */
617- static int tryReplaceSingleSameSize (ProllyMutator * pMut ){
622+ static int tryInsertOrReplaceSingleNoRechunk (ProllyMutator * pMut ){
618623 ProllyMutMapEntry * pEdit ;
619624 ProllyCursor cur ;
620625 ProllyHash childHash ;
621- i64 iKey ;
626+ i64 iKey = 0 ;
622627 int rc ;
623628 int res = 0 ;
624629 int level ;
@@ -646,13 +651,13 @@ static int tryReplaceSingleSameSize(ProllyMutator *pMut){
646651 prollyCursorClose (& cur );
647652 return rc ;
648653 }
649- if ( res != 0 || cur .eState != PROLLY_CURSOR_VALID ){
654+ if ( cur .eState != PROLLY_CURSOR_VALID ){
650655 prollyCursorClose (& cur );
651656 return SQLITE_NOTFOUND ;
652657 }
653658
654659 level = cur .iLevel ;
655- {
660+ if ( res == 0 ) {
656661 ProllyNode * pLeaf = & cur .aLevel [level ].pEntry -> node ;
657662 int idx = cur .aLevel [level ].idx ;
658663 const u8 * pOldVal ;
@@ -686,107 +691,53 @@ static int tryReplaceSingleSameSize(ProllyMutator *pMut){
686691 prollyCursorClose (& cur );
687692 return rc ;
688693 }
689- }
690694
691- while ( level > 0 ){
692- ProllyNode * pNode ;
695+ rc = rewriteAncestorSpine (pMut , & cur , level , & childHash , 0 );
696+ if ( rc == SQLITE_OK ){
697+ pMut -> newRoot = childHash ;
698+ }
699+ prollyCursorClose (& cur );
700+ return rc ;
701+ }else {
702+ ProllyNode * pLeaf ;
693703 ProllyNodeBuilder b ;
694- ProllyHash parentHash ;
695704 int idx ;
705+ int requireBoundary ;
696706 int i ;
697707
698- level -- ;
699- pNode = & cur .aLevel [level ].pEntry -> node ;
700- idx = cur .aLevel [level ].idx ;
701- prollyNodeBuilderInit (& b , (u8 )pNode -> level , pMut -> flags );
702- for (i = 0 ; i < (int )pNode -> nItems ; i ++ ){
703- u64 cnt = 0 ;
704- rc = parentChildSubtreeCount (pMut -> pStore , pMut -> pCache ,
705- pNode , i , & cnt );
706- if ( rc == SQLITE_OK ){
707- if ( i == idx ){
708- const u8 * pKey ;
709- int nKey ;
710- prollyNodeKey (pNode , i , & pKey , & nKey );
711- rc = prollyNodeBuilderAddWithCount (
712- & b , pKey , nKey , childHash .data , PROLLY_HASH_SIZE , cnt );
713- }else {
714- rc = appendNodeEntryToBuilder (& b , pNode , i , cnt );
715- }
708+ if ( pMut -> flags & PROLLY_NODE_INTKEY ){
709+ if ( iKey >=prollyCursorIntKey (& cur ) ){
710+ prollyCursorClose (& cur );
711+ return SQLITE_NOTFOUND ;
716712 }
717- if ( rc != SQLITE_OK ){
718- prollyNodeBuilderFree (& b );
713+ }else {
714+ const u8 * pCurKey ;
715+ int nCurKey ;
716+ prollyCursorKey (& cur , & pCurKey , & nCurKey );
717+ if ( compareKeys (pEdit -> pKey , pEdit -> nKey , pCurKey , nCurKey )>=0 ){
719718 prollyCursorClose (& cur );
720- return rc ;
719+ return SQLITE_NOTFOUND ;
721720 }
722721 }
723- rc = writeBuilderNode (pMut -> pStore , & b , & parentHash );
724- prollyNodeBuilderFree (& b );
725- if ( rc != SQLITE_OK ){
726- prollyCursorClose (& cur );
727- return rc ;
728- }
729- childHash = parentHash ;
730- }
731722
732- pMut -> newRoot = childHash ;
733- prollyCursorClose (& cur );
734- return SQLITE_OK ;
735- }
736-
737- static int tryDeleteSingleNoRechunk (ProllyMutator * pMut ){
738- ProllyMutMapEntry * pEdit ;
739- ProllyCursor cur ;
740- ProllyHash childHash ;
741- i64 iKey ;
742- int rc ;
743- int res = 0 ;
744- int level ;
745-
746- if ( prollyHashIsEmpty (& pMut -> oldRoot ) ) return SQLITE_NOTFOUND ;
747- if ( prollyMutMapCount (pMut -> pEdits )!= 1 ) return SQLITE_NOTFOUND ;
748-
749- pEdit = & pMut -> pEdits -> aEntries [0 ];
750- if ( pEdit -> op != PROLLY_EDIT_DELETE ){
751- return SQLITE_NOTFOUND ;
752- }
753- if ( (pMut -> flags & PROLLY_NODE_INTKEY ) && pEdit -> nKey != 8 ){
754- return SQLITE_NOTFOUND ;
755- }
756-
757- prollyCursorInit (& cur , pMut -> pStore , pMut -> pCache , & pMut -> oldRoot ,
758- pMut -> flags );
759- if ( pMut -> flags & PROLLY_NODE_INTKEY ){
760- iKey = prollyMutMapEntryIntKey (pEdit );
761- rc = prollyCursorSeekInt (& cur , iKey , & res );
762- }else {
763- rc = prollyCursorSeekBlob (& cur , pEdit -> pKey , pEdit -> nKey , & res );
764- }
765- if ( rc != SQLITE_OK ){
766- prollyCursorClose (& cur );
767- return rc ;
768- }
769- if ( res != 0 || cur .eState != PROLLY_CURSOR_VALID ){
770- prollyCursorClose (& cur );
771- return SQLITE_NOTFOUND ;
772- }
773-
774- level = cur .iLevel ;
775- {
776- ProllyNode * pLeaf = & cur .aLevel [level ].pEntry -> node ;
777- int idx = cur .aLevel [level ].idx ;
778- ProllyNodeBuilder b ;
779- int requireBoundary ;
780- int i ;
781-
782- if ( pLeaf -> nItems <=1 || idx == (int )pLeaf -> nItems - 1 ){
723+ pLeaf = & cur .aLevel [level ].pEntry -> node ;
724+ idx = cur .aLevel [level ].idx ;
725+ if ( idx < 0 || idx >=(int )pLeaf -> nItems ){
783726 prollyCursorClose (& cur );
784727 return SQLITE_NOTFOUND ;
785728 }
786729
787730 prollyNodeBuilderInit (& b , 0 , pMut -> flags );
788731 for (i = 0 ; i < (int )pLeaf -> nItems ; i ++ ){
789- if ( i == idx ) continue ;
732+ if ( i == idx ){
733+ rc = prollyNodeBuilderAdd (& b , pEdit -> pKey , pEdit -> nKey ,
734+ pEdit -> pVal , pEdit -> nVal );
735+ if ( rc != SQLITE_OK ){
736+ prollyNodeBuilderFree (& b );
737+ prollyCursorClose (& cur );
738+ return rc ;
739+ }
740+ }
790741 rc = appendNodeEntryToBuilder (& b , pLeaf , i , 0 );
791742 if ( rc != SQLITE_OK ){
792743 prollyNodeBuilderFree (& b );
@@ -802,21 +753,21 @@ static int tryDeleteSingleNoRechunk(ProllyMutator *pMut){
802753 prollyCursorClose (& cur );
803754 return rc ;
804755 }
805- }
806756
807- rc = rewriteAncestorSpine (pMut , & cur , level , & childHash , -1 );
808- if ( rc == SQLITE_OK ){
809- pMut -> newRoot = childHash ;
757+ rc = rewriteAncestorSpine (pMut , & cur , level , & childHash , 1 );
758+ if ( rc == SQLITE_OK ){
759+ pMut -> newRoot = childHash ;
760+ }
761+ prollyCursorClose (& cur );
762+ return rc ;
810763 }
811- prollyCursorClose (& cur );
812- return rc ;
813764}
814765
815- static int tryInsertSingleNoRechunk (ProllyMutator * pMut ){
766+ static int tryDeleteSingleNoRechunk (ProllyMutator * pMut ){
816767 ProllyMutMapEntry * pEdit ;
817768 ProllyCursor cur ;
818769 ProllyHash childHash ;
819- i64 iKey = 0 ;
770+ i64 iKey ;
820771 int rc ;
821772 int res = 0 ;
822773 int level ;
@@ -825,7 +776,7 @@ static int tryInsertSingleNoRechunk(ProllyMutator *pMut){
825776 if ( prollyMutMapCount (pMut -> pEdits )!= 1 ) return SQLITE_NOTFOUND ;
826777
827778 pEdit = & pMut -> pEdits -> aEntries [0 ];
828- if ( pEdit -> op != PROLLY_EDIT_INSERT ){
779+ if ( pEdit -> op != PROLLY_EDIT_DELETE ){
829780 return SQLITE_NOTFOUND ;
830781 }
831782 if ( (pMut -> flags & PROLLY_NODE_INTKEY ) && pEdit -> nKey != 8 ){
@@ -844,26 +795,11 @@ static int tryInsertSingleNoRechunk(ProllyMutator *pMut){
844795 prollyCursorClose (& cur );
845796 return rc ;
846797 }
847- if ( res = =0 || cur .eState != PROLLY_CURSOR_VALID ){
798+ if ( res ! =0 || cur .eState != PROLLY_CURSOR_VALID ){
848799 prollyCursorClose (& cur );
849800 return SQLITE_NOTFOUND ;
850801 }
851802
852- if ( pMut -> flags & PROLLY_NODE_INTKEY ){
853- if ( iKey >=prollyCursorIntKey (& cur ) ){
854- prollyCursorClose (& cur );
855- return SQLITE_NOTFOUND ;
856- }
857- }else {
858- const u8 * pCurKey ;
859- int nCurKey ;
860- prollyCursorKey (& cur , & pCurKey , & nCurKey );
861- if ( compareKeys (pEdit -> pKey , pEdit -> nKey , pCurKey , nCurKey )>=0 ){
862- prollyCursorClose (& cur );
863- return SQLITE_NOTFOUND ;
864- }
865- }
866-
867803 level = cur .iLevel ;
868804 {
869805 ProllyNode * pLeaf = & cur .aLevel [level ].pEntry -> node ;
@@ -872,22 +808,14 @@ static int tryInsertSingleNoRechunk(ProllyMutator *pMut){
872808 int requireBoundary ;
873809 int i ;
874810
875- if ( idx < 0 || idx >= (int )pLeaf -> nItems ){
811+ if ( pLeaf -> nItems <= 1 || idx == (int )pLeaf -> nItems - 1 ){
876812 prollyCursorClose (& cur );
877813 return SQLITE_NOTFOUND ;
878814 }
879815
880816 prollyNodeBuilderInit (& b , 0 , pMut -> flags );
881817 for (i = 0 ; i < (int )pLeaf -> nItems ; i ++ ){
882- if ( i == idx ){
883- rc = prollyNodeBuilderAdd (& b , pEdit -> pKey , pEdit -> nKey ,
884- pEdit -> pVal , pEdit -> nVal );
885- if ( rc != SQLITE_OK ){
886- prollyNodeBuilderFree (& b );
887- prollyCursorClose (& cur );
888- return rc ;
889- }
890- }
818+ if ( i == idx ) continue ;
891819 rc = appendNodeEntryToBuilder (& b , pLeaf , i , 0 );
892820 if ( rc != SQLITE_OK ){
893821 prollyNodeBuilderFree (& b );
@@ -905,7 +833,7 @@ static int tryInsertSingleNoRechunk(ProllyMutator *pMut){
905833 }
906834 }
907835
908- rc = rewriteAncestorSpine (pMut , & cur , level , & childHash , 1 );
836+ rc = rewriteAncestorSpine (pMut , & cur , level , & childHash , - 1 );
909837 if ( rc == SQLITE_OK ){
910838 pMut -> newRoot = childHash ;
911839 }
@@ -1136,16 +1064,13 @@ int prollyMutateFlush(ProllyMutator *pMut){
11361064 if ( prollyHashIsEmpty (& pMut -> oldRoot ) ){
11371065 rc = buildFromEdits (pMut );
11381066 }else {
1139- rc = tryReplaceSingleSameSize (pMut );
1067+ rc = tryInsertOrReplaceSingleNoRechunk (pMut );
11401068 if ( rc == SQLITE_NOTFOUND ){
11411069 rc = tryAppendSingleIntNoSplit (pMut );
11421070 }
11431071 if ( rc == SQLITE_NOTFOUND ){
11441072 rc = tryDeleteSingleNoRechunk (pMut );
11451073 }
1146- if ( rc == SQLITE_NOTFOUND ){
1147- rc = tryInsertSingleNoRechunk (pMut );
1148- }
11491074 if ( rc == SQLITE_NOTFOUND ){
11501075 rc = streamingMerge (pMut );
11511076 }
0 commit comments