@@ -15,60 +15,153 @@ package sqlite3
15
15
#include <sqlite3.h>
16
16
#endif
17
17
#include <stdlib.h>
18
+ #include <stdint.h>
18
19
*/
19
20
import "C"
21
+ import (
22
+ "fmt"
23
+ "unsafe"
24
+ )
25
+
26
+ type Session struct {
27
+ session * C.sqlite3_session
28
+ }
29
+
30
+ type Changeset struct {
31
+ changeset * C.sqlite3_changeset_iter
32
+ }
20
33
21
34
// CreateSession creates a new session object.
22
- func (c * SQLiteConn ) CreateSession () error {
23
- return nil
35
+ func (c * SQLiteConn ) CreateSession (dbName string ) (* Session , error ) {
36
+ cDbName := C .CString (dbName )
37
+ defer C .free (unsafe .Pointer (cDbName ))
38
+
39
+ var session * C.sqlite3_session
40
+ rc := C .sqlite3session_create (c .db , cDbName , & session )
41
+ if rc != C .SQLITE_OK {
42
+ return nil , fmt .Errorf ("sqlite3session_create: %s" , C .GoString (C .sqlite3_errstr (rc )))
43
+ }
44
+ return & Session {session : session }, nil
24
45
}
25
46
26
- // AttachSession attaches a session object to a set of tables.
27
- func (c * SQLiteConn ) AttachSession () error {
47
+ // AttachSession attaches a session object to a table or all tables.
48
+ func (s * Session ) AttachSession (tableName string ) error {
49
+ var cTableName * C.char
50
+ if tableName != "" {
51
+ cTableName = C .CString (tableName )
52
+ defer C .free (unsafe .Pointer (cTableName ))
53
+ }
54
+
55
+ rc := C .sqlite3session_attach (s .session , cTableName )
56
+ if rc != C .SQLITE_OK {
57
+ return fmt .Errorf ("sqlite3session_attach: %s" , C .GoString (C .sqlite3_errstr (rc )))
58
+ }
28
59
return nil
29
60
}
30
61
31
- // DetachSession deletes a session object.
32
- func (c * SQLiteConn ) DeleteSession () error {
62
+ // Delete deletes a session object.
63
+ func (s * Session ) DeleteSession () error {
64
+ if s .session != nil {
65
+ // Call sqlite3session_delete to free the session object
66
+ C .sqlite3session_delete (s .session )
67
+ s .session = nil // Set session to nil to avoid double deletion
68
+ }
33
69
return nil
34
70
}
35
71
36
- // SessionChangeset generates a changeset from a session object.
37
- func (c * SQLiteConn ) Changeset () error {
38
- return nil
72
+ type ChangesetIter struct {
73
+ iter * C.sqlite3_changeset_iter
39
74
}
40
75
41
- // ChangesetStart is called to create and initialize an iterator
42
- // to iterate through the contents of a changeset. Initially, the
43
- // iterator points to no element at all
44
- func (c * SQLiteConn ) ChangesetStart () error {
45
- return nil
76
+ // Changeset generates a changeset from a session object.
77
+ func (s * Session ) Changeset () ([]byte , error ) {
78
+ var nChangeset C.int
79
+ var pChangeset unsafe.Pointer
80
+
81
+ // Call sqlite3session_changeset
82
+ rc := C .sqlite3session_changeset (s .session , & nChangeset , & pChangeset )
83
+ if rc != C .SQLITE_OK {
84
+ return nil , fmt .Errorf ("sqlite3session_changeset: %s" , C .GoString (C .sqlite3_errstr (rc )))
85
+ }
86
+ defer C .sqlite3_free (pChangeset ) // Free the changeset buffer after use
87
+
88
+ // Convert the C buffer to a Go byte slice
89
+ changeset := C .GoBytes (pChangeset , nChangeset )
90
+ return changeset , nil
46
91
}
47
92
48
- // ChangesetNext moves a Changeset iterator to the next change in the
49
- // changeset.
50
- func (c * SQLiteConn ) ChangesetNext () error {
51
- return nil
93
+ // ChangesetStart creates and initializes a changeset iterator.
94
+ func ChangesetStart (changeset []byte ) (* ChangesetIter , error ) {
95
+ var iter * C.sqlite3_changeset_iter
96
+
97
+ // Call sqlite3changeset_start
98
+ rc := C .sqlite3changeset_start (& iter , C .int (len (changeset )), unsafe .Pointer (& changeset [0 ]))
99
+ if rc != C .SQLITE_OK {
100
+ return nil , fmt .Errorf ("sqlite3changeset_start: %s" , C .GoString (C .sqlite3_errstr (rc )))
101
+ }
102
+
103
+ return & ChangesetIter {iter : iter }, nil
52
104
}
53
105
54
- // ChangesetOp retuns the type of change (INSERT, UPDATE or DELETE)
55
- // that the iterator points to
56
- func (c * SQLiteConn ) ChangesetOp () error {
57
- return nil
106
+ // ChangesetNext moves the changeset iterator to the next change.
107
+ func (ci * ChangesetIter ) ChangesetNext () (bool , error ) {
108
+ rc := C .sqlite3changeset_next (ci .iter )
109
+ if rc == C .SQLITE_DONE {
110
+ return false , nil // No more changes
111
+ }
112
+ if rc != C .SQLITE_OK {
113
+ return false , fmt .Errorf ("sqlite3changeset_next: %s" , C .GoString (C .sqlite3_errstr (rc )))
114
+ }
115
+ return true , nil
58
116
}
59
117
60
- // ChangesetOld may be used to obtain the old.* values within the change payload.
61
- func (c * SQLiteConn ) ChangesetOld () error {
62
- return nil
118
+ // ChangesetOp returns the type of change (INSERT, UPDATE, or DELETE) that the iterator points to.
119
+ func (ci * ChangesetIter ) ChangesetOp () (string , int , int , bool , error ) {
120
+ var tableName * C.char
121
+ var nCol C.int
122
+ var op C.int
123
+ var indirect C.int
124
+
125
+ rc := C .sqlite3changeset_op (ci .iter , & tableName , & nCol , & op , & indirect )
126
+ if rc != C .SQLITE_OK {
127
+ return "" , 0 , 0 , false , fmt .Errorf ("sqlite3changeset_op: %s" , C .GoString (C .sqlite3_errstr (rc )))
128
+ }
129
+
130
+ return C .GoString (tableName ), int (nCol ), int (op ), indirect != 0 , nil
63
131
}
64
132
65
- // ChangesetNew may be used to obtain the new.* values within the change payload.
66
- func (c * SQLiteConn ) ChangesetNew () error {
67
- return nil
133
+ // ChangesetOld retrieves the old value for the specified column in the change payload.
134
+ func (ci * ChangesetIter ) ChangesetOld (column int ) (* C.sqlite3_value , error ) {
135
+ var value * C.sqlite3_value
136
+
137
+ rc := C .sqlite3changeset_old (ci .iter , C .int (column ), & value )
138
+ if rc != C .SQLITE_OK {
139
+ return nil , fmt .Errorf ("sqlite3changeset_old: %s" , C .GoString (C .sqlite3_errstr (rc )))
140
+ }
141
+
142
+ return value , nil
68
143
}
69
144
70
- // ChangesetFinalize is called to delete a changeste iterator.
71
- func (c * SQLiteConn ) ChangesetFinalize () error {
72
- return nil
145
+ // ChangesetNew retrieves the new value for the specified column in the change payload.
146
+ func (ci * ChangesetIter ) ChangesetNew (column int ) (* C.sqlite3_value , error ) {
147
+ var value * C.sqlite3_value
148
+
149
+ rc := C .sqlite3changeset_new (ci .iter , C .int (column ), & value )
150
+ if rc != C .SQLITE_OK {
151
+ return nil , fmt .Errorf ("sqlite3changeset_new: %s" , C .GoString (C .sqlite3_errstr (rc )))
152
+ }
153
+
154
+ return value , nil
73
155
}
74
156
157
+ // ChangesetFinalize deletes a changeset iterator.
158
+ func (ci * ChangesetIter ) ChangesetFinalize () error {
159
+ if ci .iter != nil {
160
+ rc := C .sqlite3changeset_finalize (ci .iter )
161
+ ci .iter = nil // Prevent double finalization
162
+ if rc != C .SQLITE_OK {
163
+ return fmt .Errorf ("sqlite3changeset_finalize: %s" , C .GoString (C .sqlite3_errstr (rc )))
164
+ }
165
+ }
166
+ return nil
167
+ }
0 commit comments