@@ -1021,35 +1021,65 @@ END;
1021
1021
});
1022
1022
1023
1023
group ('raw tables' , () {
1024
- syncTest ('smoke test' , (_) {
1025
- db.execute (
1026
- 'CREATE TABLE users (id TEXT NOT NULL PRIMARY KEY, name TEXT NOT NULL) STRICT;' );
1027
-
1028
- invokeControl (
1029
- 'start' ,
1030
- json.encode ({
1031
- 'schema' : {
1032
- 'raw_tables' : [
1033
- {
1034
- 'name' : 'users' ,
1035
- 'put' : {
1036
- 'sql' :
1037
- 'INSERT OR REPLACE INTO users (id, name) VALUES (?, ?);' ,
1038
- 'params' : [
1039
- 'Id' ,
1040
- {'Column' : 'name' }
1041
- ],
1042
- },
1043
- 'delete' : {
1044
- 'sql' : 'DELETE FROM users WHERE id = ?' ,
1045
- 'params' : ['Id' ],
1046
- },
1047
- }
1024
+ const schema = {
1025
+ 'raw_tables' : [
1026
+ {
1027
+ 'name' : 'users' ,
1028
+ 'put' : {
1029
+ 'sql' : 'INSERT OR REPLACE INTO users (id, name) VALUES (?, ?);' ,
1030
+ 'params' : [
1031
+ 'Id' ,
1032
+ {'Column' : 'name' }
1048
1033
],
1049
- 'tables' : [],
1050
1034
},
1051
- }),
1052
- );
1035
+ 'delete' : {
1036
+ 'sql' : 'DELETE FROM users WHERE id = ?' ,
1037
+ 'params' : ['Id' ],
1038
+ },
1039
+ }
1040
+ ],
1041
+ 'tables' : [],
1042
+ };
1043
+
1044
+ void setupRawTables () {
1045
+ db.execute ('''
1046
+ CREATE TABLE users (id TEXT NOT NULL PRIMARY KEY, name TEXT NOT NULL) STRICT;
1047
+
1048
+ CREATE TRIGGER users_insert
1049
+ AFTER INSERT ON users
1050
+ FOR EACH ROW
1051
+ BEGIN
1052
+ INSERT INTO powersync_crud (op, id, type, data) VALUES ('PUT', NEW.id, 'users', json_object(
1053
+ 'name', NEW.name
1054
+ ));
1055
+ END;
1056
+
1057
+ CREATE TRIGGER users_update
1058
+ AFTER UPDATE ON users
1059
+ FOR EACH ROW
1060
+ BEGIN
1061
+ SELECT CASE
1062
+ WHEN (OLD.id != NEW.id)
1063
+ THEN RAISE (FAIL, 'Cannot update id')
1064
+ END;
1065
+
1066
+ INSERT INTO powersync_crud (op, id, type, data) VALUES ('PATCH', NEW.id, 'users', json_object(
1067
+ 'name', NEW.name
1068
+ ));
1069
+ END;
1070
+
1071
+ CREATE TRIGGER users_delete
1072
+ AFTER DELETE ON users
1073
+ FOR EACH ROW
1074
+ BEGIN
1075
+ INSERT INTO powersync_crud (op, id, type) VALUES ('DELETE', OLD.id, 'users');
1076
+ END;
1077
+ ''' );
1078
+ }
1079
+
1080
+ syncTest ('smoke test' , (_) {
1081
+ setupRawTables ();
1082
+ invokeControl ('start' , json.encode ({'schema' : schema}));
1053
1083
1054
1084
// Insert
1055
1085
pushCheckpoint (buckets: [bucketDescription ('a' )]);
@@ -1083,34 +1113,71 @@ END;
1083
1113
expect (db.select ('SELECT * FROM users' ), isEmpty);
1084
1114
});
1085
1115
1086
- test ("crud vtab is no-op during sync" , () {
1087
- db. execute (
1088
- 'CREATE TABLE users (id TEXT NOT NULL PRIMARY KEY, name TEXT NOT NULL) STRICT;' );
1116
+ test ('reports errors from underlying statements' , () {
1117
+ setupRawTables ();
1118
+ invokeControl ( 'start' , json. encode ({ 'schema' : schema}) );
1089
1119
1090
- invokeControl (
1091
- 'start' ,
1092
- json.encode ({
1093
- 'schema' : {
1094
- 'raw_tables' : [
1095
- {
1096
- 'name' : 'users' ,
1097
- 'put' : {
1098
- 'sql' : "INSERT INTO powersync_crud_(data) VALUES (?);" ,
1099
- 'params' : [
1100
- {'Column' : 'name' }
1101
- ],
1102
- },
1103
- 'delete' : {
1104
- 'sql' : 'DELETE FROM users WHERE id = ?' ,
1105
- 'params' : ['Id' ],
1106
- },
1107
- }
1108
- ],
1109
- 'tables' : [],
1110
- },
1111
- }),
1120
+ pushCheckpoint (buckets: [bucketDescription ('a' )]);
1121
+ pushSyncData (
1122
+ 'a' ,
1123
+ '1' ,
1124
+ 'my_user' ,
1125
+ 'PUT' ,
1126
+ {},
1127
+ objectType: 'users' ,
1112
1128
);
1113
1129
1130
+ expect (
1131
+ pushCheckpointComplete,
1132
+ throwsA (
1133
+ isSqliteException (
1134
+ 1299 ,
1135
+ 'powersync_control: replacing into users, id = my_user, data = {}: '
1136
+ 'internal SQLite call returned CONSTRAINT_NOTNULL: '
1137
+ 'NOT NULL constraint failed: users.name' ,
1138
+ ),
1139
+ ),
1140
+ );
1141
+ });
1142
+
1143
+ test ('crud vtab' , () {
1144
+ // This is mostly a test for the triggers, validating the suggestions we
1145
+ // give on https://docs.powersync.com/usage/use-case-examples/raw-tables#capture-local-writes-with-triggers
1146
+ setupRawTables ();
1147
+
1148
+ db.execute ('''
1149
+ BEGIN;
1150
+ INSERT INTO users (id, name) VALUES ('test-id', 'test user');
1151
+ UPDATE users SET name = name || '2';
1152
+ DELETE FROM users;
1153
+ END;
1154
+ ''' );
1155
+
1156
+ expect (db.select ('SELECT * FROM ps_crud' ), [
1157
+ {
1158
+ 'id' : 1 ,
1159
+ 'data' :
1160
+ '{"op":"PUT","id":"test-id","type":"users","data":{"name":"test user"}}' ,
1161
+ 'tx_id' : 1
1162
+ },
1163
+ {
1164
+ 'id' : 2 ,
1165
+ 'data' :
1166
+ '{"op":"PATCH","id":"test-id","type":"users","data":{"name":"test user2"}}' ,
1167
+ 'tx_id' : 1
1168
+ },
1169
+ {
1170
+ 'id' : 3 ,
1171
+ 'data' : '{"op":"DELETE","id":"test-id","type":"users"}' ,
1172
+ 'tx_id' : 1
1173
+ },
1174
+ ]);
1175
+ });
1176
+
1177
+ test ("crud vtab is no-op during sync" , () {
1178
+ setupRawTables ();
1179
+ invokeControl ('start' , json.encode ({'schema' : schema}));
1180
+
1114
1181
// Insert
1115
1182
pushCheckpoint (buckets: [bucketDescription ('a' )]);
1116
1183
pushSyncData (
0 commit comments