@@ -4,23 +4,57 @@ import (
4
4
"context"
5
5
"io"
6
6
"path/filepath"
7
+ "reflect"
8
+ "time"
9
+
10
+ // Package imports
11
+ sqobj "github.com/mutablelogic/go-sqlite/pkg/sqobj"
7
12
8
13
// Namespace imports
9
14
. "github.com/mutablelogic/go-sqlite"
10
15
. "github.com/mutablelogic/go-sqlite/pkg/lang"
11
16
. "github.com/mutablelogic/go-sqlite/pkg/quote"
12
17
)
13
18
19
+ ///////////////////////////////////////////////////////////////////////////////
20
+ // Types
21
+
22
+ type File struct {
23
+ Name string `sqlite:"name,primary,index:name"` // Index name, primary key
24
+ Path string `sqlite:"path,primary,index:path"` // Relative path, primary key
25
+ Parent string `sqlite:"parent,index:parent"` // Parent folder
26
+ Filename string `sqlite:"filename,notnull,index:filename"` // Filename
27
+ IsDir bool `sqlite:"isdir,notnull"` // Is a directory
28
+ Ext string `sqlite:"ext,index:ext"`
29
+ ModTime time.Time `sqlite:"modtime"`
30
+ Size int64 `sqlite:"size"`
31
+ }
32
+
33
+ type Doc struct {
34
+ Name string `sqlite:"name,primary,foreign"` // Index name, primary key
35
+ Path string `sqlite:"path,primary,foreign"` // Relative path, primary key
36
+ Title string `sqlite:"title,notnull"` // Title of the document, text
37
+ Description string `sqlite:"description"` // Description of the document, text
38
+ Shortform string `sqlite:"shortform"` // Shortform of the document, html
39
+ }
40
+
41
+ type Search struct {
42
+ Name string `sqlite:"name"`
43
+ Parent string `sqlite:"parent"`
44
+ Filename string `sqlite:"filename"`
45
+ //Title string `sqlite:"title"`
46
+ //Description string `sqlite:"description"`
47
+ //Shortform string `sqlite:"shortform"`
48
+ //Text string `sqlite:"text"`
49
+ }
50
+
14
51
///////////////////////////////////////////////////////////////////////////////
15
52
// GLOBALS
16
53
17
54
const (
18
- filesTableName = "file"
19
- nameIndexName = "file_name"
55
+ fileTableName = "file"
20
56
searchTableName = "search"
21
- parentIndexName = "file_parent"
22
- filenameIndexName = "file_filename"
23
- extIndexName = "file_filename"
57
+ docTableName = "doc"
24
58
searchTriggerInsertName = "search_insert"
25
59
searchTriggerDeleteName = "search_delete"
26
60
searchTriggerUpdateName = "search_update"
@@ -30,6 +64,25 @@ const (
30
64
defaultTokenizer = "porter unicode61"
31
65
)
32
66
67
+ var (
68
+ filesTypeCast = []reflect.Type {
69
+ reflect .TypeOf ("" ),
70
+ reflect .TypeOf ("" ),
71
+ reflect .TypeOf ("" ),
72
+ reflect .TypeOf ("" ),
73
+ reflect .TypeOf (false ),
74
+ reflect .TypeOf ("" ),
75
+ reflect .TypeOf (time.Time {}),
76
+ reflect .TypeOf (int64 (0 )),
77
+ }
78
+ )
79
+
80
+ var (
81
+ fileTable = sqobj .MustRegisterClass (N (fileTableName ), File {})
82
+ docTable = sqobj .MustRegisterClass (N (docTableName ), Doc {}).ForeignKey (fileTable )
83
+ searchTable = sqobj .MustRegisterVirtual (N (searchTableName ), "fts5" , Search {}, "content=" + Quote (fileTableName ))
84
+ )
85
+
33
86
///////////////////////////////////////////////////////////////////////////////
34
87
// PUBLIC METHODS
35
88
@@ -41,64 +94,28 @@ func CreateSchema(ctx context.Context, conn SQConnection, schema string, tokeniz
41
94
42
95
// Create tables
43
96
return conn .Do (ctx , 0 , func (txn SQTransaction ) error {
44
- if _ , err := txn .Query (N (filesTableName ).WithSchema (schema ).CreateTable (
45
- C ("name" ).WithPrimary (),
46
- C ("path" ).WithPrimary (),
47
- C ("parent" ),
48
- C ("filename" ).NotNull (),
49
- C ("isdir" ).WithType ("INTEGER" ).NotNull (),
50
- C ("ext" ),
51
- C ("modtime" ),
52
- C ("size" ).WithType ("INTEGER" ),
53
- ).IfNotExists ()); err != nil {
54
- return err
55
- }
56
- // Create the file indexes
57
- if _ , err := txn .Query (N (nameIndexName ).WithSchema (schema ).CreateIndex (
58
- filesTableName , "name" ,
59
- ).IfNotExists ()); err != nil {
60
- return err
61
- }
62
- if _ , err := txn .Query (N (parentIndexName ).WithSchema (schema ).CreateIndex (
63
- filesTableName , "parent" ,
64
- ).IfNotExists ()); err != nil {
65
- return err
66
- }
67
- if _ , err := txn .Query (N (filenameIndexName ).WithSchema (schema ).CreateIndex (
68
- filesTableName , "filename" ,
69
- ).IfNotExists ()); err != nil {
70
- return err
97
+ if err := fileTable .Create (txn , schema ); err != nil {
98
+ return nil
71
99
}
72
- if _ , err := txn .Query (N (extIndexName ).WithSchema (schema ).CreateIndex (
73
- filesTableName , "ext" ,
74
- ).IfNotExists ()); err != nil {
75
- return err
100
+ if err := docTable .Create (txn , schema ); err != nil {
101
+ return nil
76
102
}
77
- // Create the search table
78
- if _ , err := txn .Query (N (searchTableName ).WithSchema (schema ).CreateVirtualTable (
79
- "fts5" ,
80
- "name" ,
81
- "parent" ,
82
- "filename" ,
83
- ).Options (
84
- "content=" + filesTableName ,
85
- "tokenize=" + Quote (tokenizer ),
86
- ).IfNotExists ()); err != nil {
87
- return err
103
+ if err := searchTable .Create (txn , schema , "tokenize=" + Quote (tokenizer )); err != nil {
104
+ return nil
88
105
}
89
106
// triggers to keep the FTS index up to date
90
107
// https://www.sqlite.org/fts5.html
91
- if _ , err := txn .Query (N (searchTriggerInsertName ).WithSchema (schema ).CreateTrigger (filesTableName ,
108
+ if _ , err := txn .Query (N (searchTriggerInsertName ).WithSchema (schema ).CreateTrigger (fileTableName ,
92
109
Q ("INSERT INTO " , searchTableName , " (rowid, name, parent, filename) VALUES (new.rowid, new.name, new.parent, new.filename)" ),
93
110
).After ().Insert ().IfNotExists ()); err != nil {
94
111
return err
95
112
}
96
- if _ , err := txn .Query (N (searchTriggerDeleteName ).WithSchema (schema ).CreateTrigger (filesTableName ,
113
+ if _ , err := txn .Query (N (searchTriggerDeleteName ).WithSchema (schema ).CreateTrigger (fileTableName ,
97
114
Q ("INSERT INTO " , searchTableName , " (" , searchTableName , ", rowid, name, parent, filename) VALUES ('delete', old.rowid, old.name, old.parent, old.filename)" ),
98
115
).After ().Delete ().IfNotExists ()); err != nil {
99
116
return err
100
117
}
101
- if _ , err := txn .Query (N (searchTriggerUpdateName ).WithSchema (schema ).CreateTrigger (filesTableName ,
118
+ if _ , err := txn .Query (N (searchTriggerUpdateName ).WithSchema (schema ).CreateTrigger (fileTableName ,
102
119
Q ("INSERT INTO " , searchTableName , " (" , searchTableName , ", rowid, name, parent, filename) VALUES ('delete', old.rowid, old.name, old.parent, old.filename)" ),
103
120
Q ("INSERT INTO " , searchTableName , " (rowid, name, parent, filename) VALUES (new.rowid, new.name, new.parent, new.filename)" ),
104
121
).After ().Update ().IfNotExists ()); err != nil {
@@ -112,7 +129,7 @@ func CreateSchema(ctx context.Context, conn SQConnection, schema string, tokeniz
112
129
func ListIndexWithCount (ctx context.Context , conn SQConnection , schema string ) (map [string ]int64 , error ) {
113
130
results := make (map [string ]int64 )
114
131
if err := conn .Do (ctx , 0 , func (txn SQTransaction ) error {
115
- s := Q ("SELECT name,COUNT(*) AS count FROM " , N (filesTableName ).WithSchema (schema ), " GROUP BY name" )
132
+ s := Q ("SELECT name,COUNT(*) AS count FROM " , N (fileTableName ).WithSchema (schema ), " GROUP BY name" )
116
133
r , err := txn .Query (s )
117
134
if err != nil && err != io .EOF {
118
135
return err
@@ -136,7 +153,7 @@ func ListIndexWithCount(ctx context.Context, conn SQConnection, schema string) (
136
153
}
137
154
138
155
func Replace (schema string , evt * QueueEvent ) (SQStatement , []interface {}) {
139
- return N (filesTableName ).WithSchema (schema ).Insert (
156
+ return N (fileTableName ).WithSchema (schema ).Insert (
140
157
"name" , "path" , "parent" , "filename" , "isdir" , "ext" , "modtime" , "size" ,
141
158
).WithConflictUpdate ("name" , "path" ),
142
159
[]interface {}{
@@ -152,16 +169,30 @@ func Replace(schema string, evt *QueueEvent) (SQStatement, []interface{}) {
152
169
}
153
170
154
171
func Delete (schema string , evt * QueueEvent ) (SQStatement , []interface {}) {
155
- return N (filesTableName ).WithSchema (schema ).Delete (Q ("name=?" ), Q ("path=?" )),
172
+ return N (fileTableName ).WithSchema (schema ).Delete (Q ("name=?" ), Q ("path=?" )),
156
173
[]interface {}{evt .Name , evt .Path }
157
174
}
158
175
176
+ func GetFile (schema string , rowid int64 ) (SQStatement , []interface {}, []reflect.Type ) {
177
+ return S (N (fileTableName ).WithSchema (schema )).
178
+ To (N ("name" ), N ("path" ), N ("parent" ), N ("filename" ), N ("isdir" ), N ("ext" ), N ("modtime" ), N ("size" )).
179
+ Where (Q ("rowid" , "=" , P )), []interface {}{rowid }, filesTypeCast
180
+ }
181
+
182
+ func UpsertDoc (txn SQTransaction , doc * Doc ) (int64 , error ) {
183
+ if n , err := docTable .UpsertKeys (txn , doc ); err != nil {
184
+ return 0 , err
185
+ } else {
186
+ return n [0 ], nil
187
+ }
188
+ }
189
+
159
190
func Query (schema string , snippet bool ) SQSelect {
160
191
// Set the query join
161
192
queryJoin := J (
162
193
N (searchTableName ).WithSchema (schema ),
163
- N (filesTableName ).WithSchema (schema ),
164
- ).LeftJoin (Q (N (searchTableName ), ".rowid=" , N (filesTableName ), ".rowid" ))
194
+ N (fileTableName ).WithSchema (schema ),
195
+ ).LeftJoin (Q (N (searchTableName ), ".rowid=" , N (fileTableName ), ".rowid" ))
165
196
// Set the snippet expression
166
197
snippetExpr := V ("" )
167
198
if snippet {
@@ -172,13 +203,13 @@ func Query(schema string, snippet bool) SQSelect {
172
203
N ("rowid" ).WithSchema (searchTableName ),
173
204
N ("rank" ).WithSchema (searchTableName ),
174
205
snippetExpr ,
175
- N ("name" ).WithSchema (filesTableName ),
176
- N ("path" ).WithSchema (filesTableName ),
177
- N ("parent" ).WithSchema (filesTableName ),
178
- N ("filename" ).WithSchema (filesTableName ),
179
- N ("isdir" ).WithSchema (filesTableName ),
180
- N ("ext" ).WithSchema (filesTableName ),
181
- N ("modtime" ).WithSchema (filesTableName ),
182
- N ("size" ).WithSchema (filesTableName ),
206
+ N ("name" ).WithSchema (fileTableName ),
207
+ N ("path" ).WithSchema (fileTableName ),
208
+ N ("parent" ).WithSchema (fileTableName ),
209
+ N ("filename" ).WithSchema (fileTableName ),
210
+ N ("isdir" ).WithSchema (fileTableName ),
211
+ N ("ext" ).WithSchema (fileTableName ),
212
+ N ("modtime" ).WithSchema (fileTableName ),
213
+ N ("size" ).WithSchema (fileTableName ),
183
214
).Where (Q (searchTableName , " MATCH " , P )).Order (N ("rank" ))
184
215
}
0 commit comments