1
1
//! Objects related to [`SqliteStore`] live here.
2
+ use crate :: utils:: check_namespace_key_validity;
3
+
2
4
use lightning:: util:: persist:: KVStore ;
3
5
use lightning:: util:: string:: PrintableString ;
4
6
@@ -15,7 +17,7 @@ pub const DEFAULT_SQLITE_DB_FILE_NAME: &str = "ldk_data.sqlite";
15
17
pub const DEFAULT_KV_TABLE_NAME : & str = "ldk_data" ;
16
18
17
19
// The current SQLite `user_version`, which we can use if we'd ever need to do a schema migration.
18
- const SCHEMA_USER_VERSION : u16 = 1 ;
20
+ const SCHEMA_USER_VERSION : u16 = 2 ;
19
21
20
22
/// A [`KVStore`] implementation that writes to and reads from an [SQLite] database.
21
23
///
@@ -56,8 +58,9 @@ impl SqliteStore {
56
58
let sql = format ! (
57
59
"CREATE TABLE IF NOT EXISTS {} (
58
60
namespace TEXT NOT NULL,
61
+ sub_namespace TEXT DEFAULT \" \" NOT NULL,
59
62
key TEXT NOT NULL CHECK (key <> ''),
60
- value BLOB, PRIMARY KEY ( namespace, key )
63
+ value BLOB, PRIMARY KEY ( namespace, sub_namespace, key )
61
64
);" ,
62
65
kv_table_name
63
66
) ;
@@ -76,27 +79,13 @@ impl SqliteStore {
76
79
}
77
80
78
81
impl KVStore for SqliteStore {
79
- fn read ( & self , namespace : & str , key : & str ) -> std:: io:: Result < Vec < u8 > > {
80
- if key. is_empty ( ) {
81
- debug_assert ! ( false , "Failed to read {}/{}: key may not be empty." ,
82
- PrintableString ( namespace) , PrintableString ( key) ) ;
83
- let msg = format ! ( "Failed to read {}/{}: key may not be empty." ,
84
- PrintableString ( namespace) , PrintableString ( key) ) ;
85
- return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg) ) ;
86
- }
87
-
88
- if namespace. chars ( ) . any ( |c| !c. is_ascii ( ) || c. is_control ( ) ) ||
89
- key. chars ( ) . any ( |c| !c. is_ascii ( ) || c. is_control ( ) ) {
90
- debug_assert ! ( false , "Failed to read {}/{}: namespace and key must be valid ASCII
91
- strings." , PrintableString ( namespace) , PrintableString ( key) ) ;
92
- let msg = format ! ( "Failed to read {}/{}: namespace and key must be valid ASCII strings." ,
93
- PrintableString ( namespace) , PrintableString ( key) ) ;
94
- return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg) ) ;
95
- }
82
+ fn read ( & self , namespace : & str , sub_namespace : & str , key : & str ) -> std:: io:: Result < Vec < u8 > > {
83
+ check_namespace_key_validity ( namespace, sub_namespace, Some ( key) , "read" ) ?;
96
84
97
85
let locked_conn = self . connection . lock ( ) . unwrap ( ) ;
98
86
let sql =
99
- format ! ( "SELECT value FROM {} WHERE namespace=:namespace AND key=:key;" , self . kv_table_name) ;
87
+ format ! ( "SELECT value FROM {} WHERE namespace=:namespace AND sub_namespace=:sub_namespace AND key=:key;" ,
88
+ self . kv_table_name) ;
100
89
101
90
let mut stmt = locked_conn. prepare_cached ( & sql) . map_err ( |e| {
102
91
let msg = format ! ( "Failed to prepare statement: {}" , e) ;
@@ -107,46 +96,35 @@ impl KVStore for SqliteStore {
107
96
. query_row (
108
97
named_params ! {
109
98
":namespace" : namespace,
99
+ ":sub_namespace" : sub_namespace,
110
100
":key" : key,
111
101
} ,
112
102
|row| row. get ( 0 ) ,
113
103
)
114
104
. map_err ( |e| match e {
115
105
rusqlite:: Error :: QueryReturnedNoRows => {
116
106
let msg =
117
- format ! ( "Failed to read as key could not be found: {}/{}" , namespace, key) ;
107
+ format ! ( "Failed to read as key could not be found: {}/{}/{}" ,
108
+ PrintableString ( namespace) , PrintableString ( sub_namespace) , PrintableString ( key) ) ;
118
109
std:: io:: Error :: new ( std:: io:: ErrorKind :: NotFound , msg)
119
110
}
120
111
e => {
121
- let msg = format ! ( "Failed to read from key {}/{}: {}" , namespace, key, e) ;
112
+ let msg = format ! ( "Failed to read from key {}/{}/{}: {}" ,
113
+ PrintableString ( namespace) , PrintableString ( sub_namespace) ,
114
+ PrintableString ( key) , e) ;
122
115
std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg)
123
116
}
124
117
} ) ?;
125
118
Ok ( res)
126
119
}
127
120
128
- fn write ( & self , namespace : & str , key : & str , buf : & [ u8 ] ) -> std:: io:: Result < ( ) > {
129
- if key. is_empty ( ) {
130
- debug_assert ! ( false , "Failed to write {}/{}: key may not be empty." ,
131
- PrintableString ( namespace) , PrintableString ( key) ) ;
132
- let msg = format ! ( "Failed to write {}/{}: key may not be empty." ,
133
- PrintableString ( namespace) , PrintableString ( key) ) ;
134
- return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg) ) ;
135
- }
136
-
137
- if namespace. chars ( ) . any ( |c| !c. is_ascii ( ) || c. is_control ( ) ) ||
138
- key. chars ( ) . any ( |c| !c. is_ascii ( ) || c. is_control ( ) ) {
139
- debug_assert ! ( false , "Failed to write {}/{}: namespace and key must be valid ASCII
140
- strings." , PrintableString ( namespace) , PrintableString ( key) ) ;
141
- let msg = format ! ( "Failed to write {}/{}: namespace and key must be valid ASCII strings." ,
142
- PrintableString ( namespace) , PrintableString ( key) ) ;
143
- return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg) ) ;
144
- }
121
+ fn write ( & self , namespace : & str , sub_namespace : & str , key : & str , buf : & [ u8 ] ) -> std:: io:: Result < ( ) > {
122
+ check_namespace_key_validity ( namespace, sub_namespace, Some ( key) , "write" ) ?;
145
123
146
124
let locked_conn = self . connection . lock ( ) . unwrap ( ) ;
147
125
148
126
let sql = format ! (
149
- "INSERT OR REPLACE INTO {} (namespace, key, value) VALUES (:namespace, :key, :value);" ,
127
+ "INSERT OR REPLACE INTO {} (namespace, sub_namespace, key, value) VALUES (:namespace, :sub_namespace , :key, :value);" ,
150
128
self . kv_table_name
151
129
) ;
152
130
@@ -158,38 +136,26 @@ impl KVStore for SqliteStore {
158
136
stmt. execute (
159
137
named_params ! {
160
138
":namespace" : namespace,
139
+ ":sub_namespace" : sub_namespace,
161
140
":key" : key,
162
141
":value" : buf,
163
142
} ,
164
143
)
165
144
. map ( |_| ( ) )
166
145
. map_err ( |e| {
167
- let msg = format ! ( "Failed to write to key {}/{}: {}" , namespace, key, e) ;
146
+ let msg = format ! ( "Failed to write to key {}/{}/{}: {}" ,
147
+ PrintableString ( namespace) , PrintableString ( sub_namespace) ,
148
+ PrintableString ( key) , e) ;
168
149
std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg)
169
150
} )
170
151
}
171
152
172
- fn remove ( & self , namespace : & str , key : & str ) -> lightning:: io:: Result < ( ) > {
173
- if key. is_empty ( ) {
174
- debug_assert ! ( false , "Failed to remove {}/{}: key may not be empty." ,
175
- PrintableString ( namespace) , PrintableString ( key) ) ;
176
- let msg = format ! ( "Failed to remove {}/{}: key may not be empty." ,
177
- PrintableString ( namespace) , PrintableString ( key) ) ;
178
- return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg) ) ;
179
- }
180
-
181
- if namespace. chars ( ) . any ( |c| !c. is_ascii ( ) || c. is_control ( ) ) ||
182
- key. chars ( ) . any ( |c| !c. is_ascii ( ) || c. is_control ( ) ) {
183
- debug_assert ! ( false , "Failed to remove {}/{}: namespace and key must be valid ASCII
184
- strings." , PrintableString ( namespace) , PrintableString ( key) ) ;
185
- let msg = format ! ( "Failed to remove {}/{}: namespace and key must be valid ASCII strings." ,
186
- PrintableString ( namespace) , PrintableString ( key) ) ;
187
- return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg) ) ;
188
- }
153
+ fn remove ( & self , namespace : & str , sub_namespace : & str , key : & str , lazy : bool ) -> std:: io:: Result < ( ) > {
154
+ check_namespace_key_validity ( namespace, sub_namespace, Some ( key) , "remove" ) ?;
189
155
190
156
let locked_conn = self . connection . lock ( ) . unwrap ( ) ;
191
157
192
- let sql = format ! ( "DELETE FROM {} WHERE namespace=:namespace AND key=:key;" , self . kv_table_name) ;
158
+ let sql = format ! ( "DELETE FROM {} WHERE namespace=:namespace AND sub_namespace=:sub_namespace AND key=:key;" , self . kv_table_name) ;
193
159
194
160
let mut stmt = locked_conn. prepare_cached ( & sql) . map_err ( |e| {
195
161
let msg = format ! ( "Failed to prepare statement: {}" , e) ;
@@ -199,20 +165,25 @@ impl KVStore for SqliteStore {
199
165
stmt. execute (
200
166
named_params ! {
201
167
":namespace" : namespace,
168
+ ":sub_namespace" : sub_namespace,
202
169
":key" : key,
203
170
} ,
204
171
)
205
172
. map_err ( |e| {
206
- let msg = format ! ( "Failed to delete key {}/{}: {}" , namespace, key, e) ;
173
+ let msg = format ! ( "Failed to delete key {}/{}/{}: {}" ,
174
+ PrintableString ( namespace) , PrintableString ( sub_namespace) ,
175
+ PrintableString ( key) , e) ;
207
176
std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg)
208
177
} ) ?;
209
178
Ok ( ( ) )
210
179
}
211
180
212
- fn list ( & self , namespace : & str ) -> std:: io:: Result < Vec < String > > {
181
+ fn list ( & self , namespace : & str , sub_namespace : & str ) -> std:: io:: Result < Vec < String > > {
182
+ check_namespace_key_validity ( namespace, sub_namespace, None , "list" ) ?;
183
+
213
184
let locked_conn = self . connection . lock ( ) . unwrap ( ) ;
214
185
215
- let sql = format ! ( "SELECT key FROM {} WHERE namespace=:namespace" , self . kv_table_name) ;
186
+ let sql = format ! ( "SELECT key FROM {} WHERE namespace=:namespace AND sub_namespace=:sub_namespace " , self . kv_table_name) ;
216
187
let mut stmt = locked_conn. prepare_cached ( & sql) . map_err ( |e| {
217
188
let msg = format ! ( "Failed to prepare statement: {}" , e) ;
218
189
std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg)
@@ -221,7 +192,11 @@ impl KVStore for SqliteStore {
221
192
let mut keys = Vec :: new ( ) ;
222
193
223
194
let rows_iter = stmt
224
- . query_map ( named_params ! { ":namespace" : namespace, } , |row| row. get ( 0 ) )
195
+ . query_map (
196
+ named_params ! {
197
+ ":namespace" : namespace,
198
+ ":sub_namespace" : sub_namespace,
199
+ } , |row| row. get ( 0 ) )
225
200
. map_err ( |e| {
226
201
let msg = format ! ( "Failed to retrieve queried rows: {}" , e) ;
227
202
std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , msg)
0 commit comments