From 9d57a674d775d34e4b7360689227667c70e29c47 Mon Sep 17 00:00:00 2001
From: cheme <emericchevalier.pro@gmail.com>
Date: Fri, 6 May 2022 15:22:39 +0200
Subject: [PATCH] Parity-db `Change` missing implementation.  (#11049)

* support for release as in kvdb (only if no rc).

* Start impl

* minimal implementation for paritydb rc

* Update client/db/src/parity_db.rs

Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com>

* Update client/db/src/parity_db.rs

Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com>

* Update client/db/src/parity_db.rs

Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com>

* Commit not panicking in DbAdapter

* errors from string

* update parity db version

Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com>
---
 substrate/Cargo.lock                 |  4 +--
 substrate/client/db/Cargo.toml       |  2 +-
 substrate/client/db/src/parity_db.rs | 54 ++++++++++++++++++++++++----
 3 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index 1e75fc0af75..907c917d723 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -6832,9 +6832,9 @@ dependencies = [
 
 [[package]]
 name = "parity-db"
-version = "0.3.12"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e73cd0b0a78045276b19eaae8eaaa20e44a1da9a0217ff934a810d9492ae701"
+checksum = "55a7901b85874402471e131de3332dde0e51f38432c69a3853627c8e25433048"
 dependencies = [
  "blake2-rfc",
  "crc32fast",
diff --git a/substrate/client/db/Cargo.toml b/substrate/client/db/Cargo.toml
index 3c20cec72c6..e548887e56f 100644
--- a/substrate/client/db/Cargo.toml
+++ b/substrate/client/db/Cargo.toml
@@ -22,7 +22,7 @@ kvdb-memorydb = "0.11.0"
 kvdb-rocksdb = { version = "0.15.2", optional = true }
 linked-hash-map = "0.5.4"
 log = "0.4.16"
-parity-db = { version = "0.3.12", optional = true }
+parity-db = { version = "0.3.13", optional = true }
 parking_lot = "0.12.0"
 sc-client-api = { version = "4.0.0-dev", path = "../api" }
 sc-state-db = { version = "0.10.0-dev", path = "../state-db" }
diff --git a/substrate/client/db/src/parity_db.rs b/substrate/client/db/src/parity_db.rs
index f88e6f2e916..7ce1d6a6834 100644
--- a/substrate/client/db/src/parity_db.rs
+++ b/substrate/client/db/src/parity_db.rs
@@ -86,15 +86,57 @@ pub fn open<H: Clone + AsRef<[u8]>>(
 	Ok(std::sync::Arc::new(DbAdapter(db)))
 }
 
+fn ref_counted_column(col: u32) -> bool {
+	col == columns::TRANSACTION || col == columns::STATE
+}
+
 impl<H: Clone + AsRef<[u8]>> Database<H> for DbAdapter {
 	fn commit(&self, transaction: Transaction<H>) -> Result<(), DatabaseError> {
-		handle_err(self.0.commit(transaction.0.into_iter().map(|change| match change {
-			Change::Set(col, key, value) => (col as u8, key, Some(value)),
-			Change::Remove(col, key) => (col as u8, key, None),
-			_ => unimplemented!(),
-		})));
+		let mut not_ref_counted_column = Vec::new();
+		let result = self.0.commit(transaction.0.into_iter().filter_map(|change| {
+			Some(match change {
+				Change::Set(col, key, value) => (col as u8, key, Some(value)),
+				Change::Remove(col, key) => (col as u8, key, None),
+				Change::Store(col, key, value) =>
+					if ref_counted_column(col) {
+						(col as u8, key.as_ref().to_vec(), Some(value))
+					} else {
+						if !not_ref_counted_column.contains(&col) {
+							not_ref_counted_column.push(col);
+						}
+						return None
+					},
+				Change::Reference(col, key) =>
+					if ref_counted_column(col) {
+						// FIXME accessing value is not strictly needed, optimize this in parity-db.
+						let value = <Self as Database<H>>::get(self, col, key.as_ref());
+						(col as u8, key.as_ref().to_vec(), value)
+					} else {
+						if !not_ref_counted_column.contains(&col) {
+							not_ref_counted_column.push(col);
+						}
+						return None
+					},
+				Change::Release(col, key) =>
+					if ref_counted_column(col) {
+						(col as u8, key.as_ref().to_vec(), None)
+					} else {
+						if !not_ref_counted_column.contains(&col) {
+							not_ref_counted_column.push(col);
+						}
+						return None
+					},
+			})
+		}));
+
+		if not_ref_counted_column.len() > 0 {
+			return Err(DatabaseError(Box::new(parity_db::Error::InvalidInput(format!(
+				"Ref counted operation on non ref counted columns {:?}",
+				not_ref_counted_column
+			)))))
+		}
 
-		Ok(())
+		result.map_err(|e| DatabaseError(Box::new(e)))
 	}
 
 	fn get(&self, col: ColumnId, key: &[u8]) -> Option<Vec<u8>> {
-- 
GitLab