@@ -2,6 +2,7 @@ extern crate alloc;
2
2
3
3
use alloc:: boxed:: Box ;
4
4
use alloc:: string:: String ;
5
+ use const_format:: formatcp;
5
6
use core:: ffi:: { c_char, c_int, c_void} ;
6
7
7
8
use sqlite:: { Connection , ResultCode , Value } ;
@@ -11,10 +12,11 @@ use sqlite_nostd::ResultCode::NULL;
11
12
12
13
use crate :: error:: SQLiteError ;
13
14
use crate :: ext:: SafeManagedStmt ;
15
+ use crate :: schema:: TableInfoFlags ;
14
16
use crate :: vtab_util:: * ;
15
17
16
18
// Structure:
17
- // CREATE TABLE powersync_crud_(data TEXT);
19
+ // CREATE TABLE powersync_crud_(data TEXT, options INT HIDDEN );
18
20
//
19
21
// This is a insert-only virtual table. It generates transaction ids in ps_tx, and inserts data in
20
22
// ps_crud(tx_id, data).
@@ -39,7 +41,10 @@ extern "C" fn connect(
39
41
vtab : * mut * mut sqlite:: vtab ,
40
42
_err : * mut * mut c_char ,
41
43
) -> c_int {
42
- if let Err ( rc) = sqlite:: declare_vtab ( db, "CREATE TABLE powersync_crud_(data TEXT);" ) {
44
+ if let Err ( rc) = sqlite:: declare_vtab (
45
+ db,
46
+ "CREATE TABLE powersync_crud_(data TEXT, options INT HIDDEN);" ,
47
+ ) {
43
48
return rc as c_int ;
44
49
}
45
50
@@ -70,7 +75,16 @@ extern "C" fn disconnect(vtab: *mut sqlite::vtab) -> c_int {
70
75
fn begin_impl ( tab : & mut VirtualTable ) -> Result < ( ) , SQLiteError > {
71
76
let db = tab. db ;
72
77
73
- let insert_statement = db. prepare_v3 ( "INSERT INTO ps_crud(tx_id, data) VALUES (?1, ?2)" , 0 ) ?;
78
+ const SQL : & str = formatcp ! (
79
+ "\
80
+ WITH insertion (tx_id, data) AS (VALUES (?1, ?2))
81
+ INSERT INTO ps_crud(tx_id, data)
82
+ SELECT * FROM insertion WHERE (NOT (?3 & {})) OR data->>'op' != 'PATCH' OR data->'data' != '{{}}';
83
+ " ,
84
+ TableInfoFlags :: IGNORE_EMPTY_UPDATE
85
+ ) ;
86
+
87
+ let insert_statement = db. prepare_v3 ( SQL , 0 ) ?;
74
88
tab. insert_statement = Some ( insert_statement) ;
75
89
76
90
// language=SQLite
@@ -107,7 +121,11 @@ extern "C" fn rollback(vtab: *mut sqlite::vtab) -> c_int {
107
121
ResultCode :: OK as c_int
108
122
}
109
123
110
- fn insert_operation ( vtab : * mut sqlite:: vtab , data : & str ) -> Result < ( ) , SQLiteError > {
124
+ fn insert_operation (
125
+ vtab : * mut sqlite:: vtab ,
126
+ data : & str ,
127
+ flags : TableInfoFlags ,
128
+ ) -> Result < ( ) , SQLiteError > {
111
129
let tab = unsafe { & mut * ( vtab. cast :: < VirtualTable > ( ) ) } ;
112
130
if tab. current_tx . is_none ( ) {
113
131
return Err ( SQLiteError (
@@ -123,6 +141,7 @@ fn insert_operation(vtab: *mut sqlite::vtab, data: &str) -> Result<(), SQLiteErr
123
141
. ok_or ( SQLiteError :: from ( NULL ) ) ?;
124
142
statement. bind_int64 ( 1 , current_tx) ?;
125
143
statement. bind_text ( 2 , data, sqlite:: Destructor :: STATIC ) ?;
144
+ statement. bind_int ( 3 , flags. 0 as i32 ) ?;
126
145
statement. exec ( ) ?;
127
146
128
147
Ok ( ( ) )
@@ -144,7 +163,11 @@ extern "C" fn update(
144
163
} else if rowid. value_type ( ) == sqlite:: ColumnType :: Null {
145
164
// INSERT
146
165
let data = args[ 2 ] . text ( ) ;
147
- let result = insert_operation ( vtab, data) ;
166
+ let flags = match args[ 3 ] . value_type ( ) {
167
+ sqlite_nostd:: ColumnType :: Null => TableInfoFlags :: default ( ) ,
168
+ _ => TableInfoFlags ( args[ 3 ] . int ( ) as u32 ) ,
169
+ } ;
170
+ let result = insert_operation ( vtab, data, flags) ;
148
171
vtab_result ( vtab, result)
149
172
} else {
150
173
// UPDATE - not supported
0 commit comments