@@ -2,20 +2,21 @@ use alloc::collections::BTreeSet;
2
2
use alloc:: format;
3
3
use alloc:: string:: String ;
4
4
5
+ use crate :: error:: { PSResult , SQLiteError } ;
5
6
use sqlite_nostd as sqlite;
6
7
use sqlite_nostd:: { ColumnType , Connection , ResultCode } ;
7
- use crate :: error:: { SQLiteError , PSResult } ;
8
8
9
9
use crate :: ext:: SafeManagedStmt ;
10
10
use crate :: util:: { internal_table_name, quote_internal_name} ;
11
11
12
-
13
12
pub fn can_update_local ( db : * mut sqlite:: sqlite3 ) -> Result < bool , SQLiteError > {
14
13
// language=SQLite
15
- let statement = db. prepare_v2 ( "\
14
+ let statement = db. prepare_v2 (
15
+ "\
16
16
SELECT group_concat(name)
17
17
FROM ps_buckets
18
- WHERE target_op > last_op AND (name = '$local' OR pending_delete = 0)" ) ?;
18
+ WHERE target_op > last_op AND (name = '$local' OR pending_delete = 0)" ,
19
+ ) ?;
19
20
20
21
if statement. step ( ) ? != ResultCode :: ROW {
21
22
return Err ( SQLiteError :: from ( ResultCode :: ABORT ) ) ;
@@ -36,15 +37,15 @@ WHERE target_op > last_op AND (name = '$local' OR pending_delete = 0)")?;
36
37
Ok ( true )
37
38
}
38
39
39
- pub fn sync_local (
40
- db : * mut sqlite:: sqlite3 , _data : & str ) -> Result < i64 , SQLiteError > {
41
-
40
+ pub fn sync_local ( db : * mut sqlite:: sqlite3 , _data : & str ) -> Result < i64 , SQLiteError > {
42
41
if !can_update_local ( db) ? {
43
42
return Ok ( 0 ) ;
44
43
}
45
44
46
45
// language=SQLite
47
- let statement = db. prepare_v2 ( "SELECT name FROM sqlite_master WHERE type='table' AND name GLOB 'ps_data_*'" ) . into_db_result ( db) ?;
46
+ let statement = db
47
+ . prepare_v2 ( "SELECT name FROM sqlite_master WHERE type='table' AND name GLOB 'ps_data_*'" )
48
+ . into_db_result ( db) ?;
48
49
let mut tables: BTreeSet < String > = BTreeSet :: new ( ) ;
49
50
50
51
while statement. step ( ) ? == ResultCode :: ROW {
@@ -60,7 +61,9 @@ pub fn sync_local(
60
61
// |--SEARCH r USING INDEX ps_oplog_by_row (row_type=? AND row_id=?)
61
62
// `--USE TEMP B-TREE FOR GROUP BY
62
63
// language=SQLite
63
- let statement = db. prepare_v2 ( "\
64
+ let statement = db
65
+ . prepare_v2 (
66
+ "\
64
67
-- 3. Group the objects from different buckets together into a single one (ops).
65
68
SELECT r.row_type as type,
66
69
r.row_id as id,
@@ -79,7 +82,9 @@ FROM ps_buckets AS buckets
79
82
WHERE r.superseded = 0
80
83
AND b.superseded = 0
81
84
-- Group for (3)
82
- GROUP BY r.row_type, r.row_id" ) . into_db_result ( db) ?;
85
+ GROUP BY r.row_type, r.row_id" ,
86
+ )
87
+ . into_db_result ( db) ?;
83
88
84
89
// TODO: cache statements
85
90
@@ -96,12 +101,16 @@ GROUP BY r.row_type, r.row_id").into_db_result(db)?;
96
101
97
102
if buckets == "[]" {
98
103
// DELETE
99
- let delete_statement = db. prepare_v2 ( & format ! ( "DELETE FROM {} WHERE id = ?" , quoted) ) . into_db_result ( db) ?;
104
+ let delete_statement = db
105
+ . prepare_v2 ( & format ! ( "DELETE FROM {} WHERE id = ?" , quoted) )
106
+ . into_db_result ( db) ?;
100
107
delete_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
101
108
delete_statement. exec ( ) ?;
102
109
} else {
103
110
// INSERT/UPDATE
104
- let insert_statement = db. prepare_v2 ( & format ! ( "REPLACE INTO {}(id, data) VALUES(?, ?)" , quoted) ) . into_db_result ( db) ?;
111
+ let insert_statement = db
112
+ . prepare_v2 ( & format ! ( "REPLACE INTO {}(id, data) VALUES(?, ?)" , quoted) )
113
+ . into_db_result ( db) ?;
105
114
insert_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
106
115
insert_statement. bind_text ( 2 , data?, sqlite:: Destructor :: STATIC ) ?;
107
116
insert_statement. exec ( ) ?;
@@ -110,14 +119,18 @@ GROUP BY r.row_type, r.row_id").into_db_result(db)?;
110
119
if buckets == "[]" {
111
120
// DELETE
112
121
// language=SQLite
113
- let delete_statement = db. prepare_v2 ( "DELETE FROM ps_untyped WHERE type = ? AND id = ?" ) . into_db_result ( db) ?;
122
+ let delete_statement = db
123
+ . prepare_v2 ( "DELETE FROM ps_untyped WHERE type = ? AND id = ?" )
124
+ . into_db_result ( db) ?;
114
125
delete_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
115
126
delete_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
116
127
delete_statement. exec ( ) ?;
117
128
} else {
118
129
// INSERT/UPDATE
119
130
// language=SQLite
120
- let insert_statement = db. prepare_v2 ( "REPLACE INTO ps_untyped(type, id, data) VALUES(?, ?, ?)" ) . into_db_result ( db) ?;
131
+ let insert_statement = db
132
+ . prepare_v2 ( "REPLACE INTO ps_untyped(type, id, data) VALUES(?, ?, ?)" )
133
+ . into_db_result ( db) ?;
121
134
insert_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
122
135
insert_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
123
136
insert_statement. bind_text ( 3 , data?, sqlite:: Destructor :: STATIC ) ?;
@@ -127,9 +140,16 @@ GROUP BY r.row_type, r.row_id").into_db_result(db)?;
127
140
}
128
141
129
142
// language=SQLite
130
- db. exec_safe ( "UPDATE ps_buckets
143
+ db. exec_safe (
144
+ "UPDATE ps_buckets
131
145
SET last_applied_op = last_op
132
- WHERE last_applied_op != last_op" ) . into_db_result ( db) ?;
146
+ WHERE last_applied_op != last_op" ,
147
+ )
148
+ . into_db_result ( db) ?;
149
+
150
+ // language=SQLite
151
+ db. exec_safe ( "insert or replace into ps_kv(key, value) values('last_synced_at', datetime())" )
152
+ . into_db_result ( db) ?;
133
153
134
154
Ok ( 1 )
135
155
}
0 commit comments