@@ -41,25 +41,40 @@ import (
41
41
"embed"
42
42
43
43
"github.com/wader/fq/format"
44
- "github.com/wader/fq/format/registry"
45
- "github.com/wader/fq/internal/mathextra"
44
+ "github.com/wader/fq/internal/mathex"
46
45
"github.com/wader/fq/pkg/bitio"
47
46
"github.com/wader/fq/pkg/decode"
47
+ "github.com/wader/fq/pkg/interp"
48
48
"github.com/wader/fq/pkg/scalar"
49
49
)
50
50
51
51
//go:embed *.jq
52
52
var sqlite3FS embed.FS
53
53
54
54
func init () {
55
- registry . MustRegister (decode.Format {
55
+ interp . RegisterFormat (decode.Format {
56
56
Name : format .SQLITE3 ,
57
57
Description : "SQLite v3 database" ,
58
58
Groups : []string {format .PROBE },
59
59
DecodeFn : sqlite3Decode ,
60
60
Functions : []string {"torepr" },
61
- Files : sqlite3FS ,
62
61
})
62
+ interp .RegisterFS (sqlite3FS )
63
+ }
64
+
65
+ type intStack struct {
66
+ s []int
67
+ }
68
+
69
+ func (s * intStack ) Push (n int ) { s .s = append (s .s , n ) }
70
+
71
+ func (s * intStack ) Pop () (int , bool ) {
72
+ if len (s .s ) == 0 {
73
+ return 0 , false
74
+ }
75
+ var n int
76
+ n , s .s = s .s [0 ], s .s [1 :]
77
+ return n , true
63
78
}
64
79
65
80
const sqlite3HeaderSize = 100
@@ -79,7 +94,7 @@ const (
79
94
serialTypeInternal11 = 11
80
95
)
81
96
82
- var serialTypeMap = scalar.SToSymStr {
97
+ var serialTypeMap = scalar.UintMapSymStr {
83
98
serialTypeNULL : "null" ,
84
99
serialTypeS8 : "int8" ,
85
100
serialTypeSBE16 : "int16" ,
@@ -94,8 +109,8 @@ var serialTypeMap = scalar.SToSymStr{
94
109
serialTypeInternal11 : "internal11" ,
95
110
}
96
111
97
- var serialTypeMapper = scalar .Fn (func (s scalar.S ) (scalar.S , error ) {
98
- typ := s . ActualS ( )
112
+ var serialTypeMapper = scalar .SintFn (func (s scalar.Sint ) (scalar.Sint , error ) {
113
+ typ := uint64 ( s . Actual )
99
114
if st , ok := serialTypeMap [typ ]; ok {
100
115
s .Description = st
101
116
} else if typ >= 12 && typ % 2 == 0 {
@@ -106,23 +121,25 @@ var serialTypeMapper = scalar.Fn(func(s scalar.S) (scalar.S, error) {
106
121
return s , nil
107
122
})
108
123
124
+ type pageType int
125
+
109
126
const (
110
- pageTypePtrmap = 0x00
111
- pageTypeBTreeIndexInterior = 0x02
112
- pageTypeBTreeTableInterior = 0x05
113
- pageTypeBTreeIndexLeaf = 0x0a
114
- pageTypeBTreeTableLeaf = 0x0d
127
+ pageTypePtrmap pageType = 0x00
128
+ pageTypeBTreeIndexInterior = 0x02
129
+ pageTypeBTreeTableInterior = 0x05
130
+ pageTypeBTreeIndexLeaf = 0x0a
131
+ pageTypeBTreeTableLeaf = 0x0d
115
132
)
116
133
117
- var pageTypeMap = scalar.UToSymStr {
134
+ var pageTypeMap = scalar.UintMapSymStr {
118
135
// pageTypePtrmap: "ptrmap",
119
136
pageTypeBTreeIndexInterior : "index_interior" ,
120
137
pageTypeBTreeTableInterior : "table_interior" ,
121
138
pageTypeBTreeIndexLeaf : "index_leaf" ,
122
139
pageTypeBTreeTableLeaf : "table_leaf" ,
123
140
}
124
141
125
- var ptrmapTypeMap = scalar.UToSymStr {
142
+ var ptrmapTypeMap = scalar.UintMapSymStr {
126
143
1 : "rootpage" ,
127
144
2 : "freepage" ,
128
145
3 : "overflow1" ,
@@ -136,13 +153,13 @@ const (
136
153
textEncodingUTF16BE = 3
137
154
)
138
155
139
- var textEncodingMap = scalar.UToSymStr {
156
+ var textEncodingMap = scalar.UintMapSymStr {
140
157
textEncodingUTF8 : "utf8" ,
141
158
textEncodingUTF16LE : "utf16le" ,
142
159
textEncodingUTF16BE : "utf16be" ,
143
160
}
144
161
145
- var versionMap = scalar.UToSymStr {
162
+ var versionMap = scalar.UintMapSymStr {
146
163
1 : "legacy" ,
147
164
2 : "wal" ,
148
165
}
@@ -164,13 +181,13 @@ func varintDecode(d *decode.D) int64 {
164
181
break
165
182
}
166
183
}
167
- return mathextra .TwosComplement (64 , n )
184
+ return mathex .TwosComplement (64 , n )
168
185
}
169
186
170
187
func sqlite3DecodeSerialType (d * decode.D , h sqlite3Header , typ int64 ) {
171
188
switch typ {
172
189
case serialTypeNULL :
173
- d .FieldValueNil ("value" )
190
+ d .FieldValueAny ("value" , nil )
174
191
case serialTypeS8 :
175
192
d .FieldS8 ("value" )
176
193
case serialTypeSBE16 :
@@ -186,9 +203,9 @@ func sqlite3DecodeSerialType(d *decode.D, h sqlite3Header, typ int64) {
186
203
case serialTypeFloatBE64 :
187
204
d .FieldF64 ("value" )
188
205
case serialTypeInteger0 :
189
- d .FieldValueU ("value" , 0 )
206
+ d .FieldValueAny ("value" , 0 )
190
207
case serialTypeInteger1 :
191
- d .FieldValueU ("value" , 1 )
208
+ d .FieldValueAny ("value" , 1 )
192
209
case 10 , 11 :
193
210
// internal, should not appear in wellformed file
194
211
default :
@@ -228,15 +245,15 @@ func sqlite3DecodeCellFreeblock(d *decode.D) uint64 {
228
245
229
246
func sqlite3CellPayloadDecode (d * decode.D , h sqlite3Header ) {
230
247
lengthStart := d .Pos ()
231
- length := d .FieldSFn ("length" , varintDecode )
248
+ length := d .FieldSintFn ("length" , varintDecode )
232
249
lengthBits := d .Pos () - lengthStart
233
250
var serialTypes []int64
234
251
d .FramedFn ((length )* 8 - lengthBits , func (d * decode.D ) {
235
252
d .FieldArray ("serials" , func (d * decode.D ) {
236
253
for ! d .End () {
237
254
serialTypes = append (
238
255
serialTypes ,
239
- d .FieldSFn ("serial" , varintDecode , serialTypeMapper ),
256
+ d .FieldSintFn ("serial" , varintDecode , serialTypeMapper ),
240
257
)
241
258
}
242
259
})
@@ -276,18 +293,18 @@ func sqlite3DecodeTreePage(d *decode.D, h sqlite3Header, x int64, payLoadLen int
276
293
d .FieldStruct ("overflow_page" , func (d * decode.D ) {
277
294
br := d .FieldRawLen ("data" , firstPayLoadLen * 8 )
278
295
nextPage = d .FieldS32 ("next_page" )
279
- d .MustCopyBits (payLoadBB , br )
296
+ d .CopyBits (payLoadBB , br )
280
297
})
281
298
282
299
payLoadLenLeft := payLoadLen - firstPayLoadLen
283
300
for nextPage != 0 {
284
301
d .SeekAbs (((nextPage - 1 ) * h .pageSize ) * 8 )
285
302
d .FieldStruct ("overflow_page" , func (d * decode.D ) {
286
303
nextPage = d .FieldS32 ("next_page" )
287
- overflowSize := mathextra . MinInt64 (h .pageSize - 4 , payLoadLenLeft )
304
+ overflowSize := mathex . Min (h .pageSize - 4 , payLoadLenLeft )
288
305
br := d .FieldRawLen ("data" , overflowSize * 8 )
289
306
payLoadLenLeft -= overflowSize
290
- d .MustCopyBits (payLoadBB , br )
307
+ d .CopyBits (payLoadBB , br )
291
308
})
292
309
}
293
310
})
@@ -299,26 +316,34 @@ func sqlite3DecodeTreePage(d *decode.D, h sqlite3Header, x int64, payLoadLen int
299
316
}
300
317
}
301
318
319
+ func sqlite3SeekPage (d * decode.D , h sqlite3Header , i int ) {
320
+ pageOffset := h .pageSize * int64 (i )
321
+ if i == 0 {
322
+ pageOffset += sqlite3HeaderSize
323
+ }
324
+ d .SeekAbs (pageOffset * 8 )
325
+ }
326
+
302
327
func sqlite3Decode (d * decode.D , in interface {}) interface {} {
303
328
var h sqlite3Header
304
329
305
330
d .FieldStruct ("header" , func (d * decode.D ) {
306
- d .FieldUTF8 ("magic" , 16 , d .AssertStr ("SQLite format 3\x00 " ))
307
- pageSizeS := d .FieldScalarU16 ("page_size" , scalar.UToSymU {1 : 65536 }) // in bytes. Must be a power of two between 512 and 32768 inclusive, or the value 1 representing a page size of 65536.
308
- d .FieldU8 ("write_version" , versionMap ) // 1 for legacy; 2 for WAL.
309
- d .FieldU8 ("read_version" , versionMap ) // . 1 for legacy; 2 for WAL.
310
- d .FieldU8 ("unused_space" ) // at the end of each page. Usually 0.
311
- d .FieldU8 ("maximum_embedded_payload_fraction" ) // . Must be 64.
312
- d .FieldU8 ("minimum_embedded_payload_fraction" ) // . Must be 32.
313
- d .FieldU8 ("leaf_payload_fraction" ) // . Must be 32.
314
- d .FieldU32 ("file_change_counter" ) //
315
- databaseSizePages := int (d .FieldU32 ("database_size_pages" )) // . The "in-header database size".
316
- d .FieldU32 ("page_number_freelist" ) // of the first freelist trunk page.
317
- d .FieldU32 ("total_number_freelist" ) // pages.
318
- d .FieldU32 ("schema_cookie" ) // .
319
- d .FieldU32 ("schema_format_number" ) // . Supported schema formats are 1, 2, 3, and 4.
320
- d .FieldU32 ("default_page_cache_size" ) // .
321
- d .FieldU32 ("page_number_largest_root_btree" ) // page when in auto-vacuum or incremental-vacuum modes, or zero otherwise.
331
+ d .FieldUTF8 ("magic" , 16 , d .StrAssert ("SQLite format 3\x00 " ))
332
+ pageSizeS := d .FieldScalarU16 ("page_size" , scalar.UintMapSymUint {1 : 65536 }) // in bytes. Must be a power of two between 512 and 32768 inclusive, or the value 1 representing a page size of 65536.
333
+ d .FieldU8 ("write_version" , versionMap ) // 1 for legacy; 2 for WAL.
334
+ d .FieldU8 ("read_version" , versionMap ) // . 1 for legacy; 2 for WAL.
335
+ d .FieldU8 ("unused_space" ) // at the end of each page. Usually 0.
336
+ d .FieldU8 ("maximum_embedded_payload_fraction" ) // . Must be 64.
337
+ d .FieldU8 ("minimum_embedded_payload_fraction" ) // . Must be 32.
338
+ d .FieldU8 ("leaf_payload_fraction" ) // . Must be 32.
339
+ d .FieldU32 ("file_change_counter" ) //
340
+ databaseSizePages := int (d .FieldU32 ("database_size_pages" )) // . The "in-header database size".
341
+ d .FieldU32 ("page_number_freelist" ) // of the first freelist trunk page.
342
+ d .FieldU32 ("total_number_freelist" ) // pages.
343
+ d .FieldU32 ("schema_cookie" ) // .
344
+ d .FieldU32 ("schema_format_number" ) // . Supported schema formats are 1, 2, 3, and 4.
345
+ d .FieldU32 ("default_page_cache_size" ) // .
346
+ d .FieldU32 ("page_number_largest_root_btree" ) // page when in auto-vacuum or incremental-vacuum modes, or zero otherwise.
322
347
textEncoding := int (d .FieldU32 ("text_encoding" , textEncodingMap ))
323
348
d .FieldU32 ("user_version" ) // " as read and set by the user_version pragma.
324
349
d .FieldU32 ("incremental_vacuum_mode" ) // False (zero) otherwise.
@@ -328,9 +353,9 @@ func sqlite3Decode(d *decode.D, in interface{}) interface{} {
328
353
d .FieldU32 ("sqlite_version_number" ) //
329
354
330
355
// TODO: nicer API for fallback?
331
- pageSize := int64 (pageSizeS .ActualU () )
356
+ pageSize := int64 (pageSizeS .Actual )
332
357
if pageSizeS .Sym != nil {
333
- pageSize = int64 (pageSizeS .SymU ())
358
+ pageSize = int64 (pageSizeS .SymUint ())
334
359
}
335
360
336
361
h = sqlite3Header {
@@ -340,21 +365,73 @@ func sqlite3Decode(d *decode.D, in interface{}) interface{} {
340
365
}
341
366
})
342
367
343
- d .FieldArray ("pages" , func (d * decode.D ) {
344
- d .RangeSorted = false
368
+ // pageTypes := map[int]pageType{}
369
+ // pageVisitStack := &intStack{}
370
+ // pageVisitStack.Push(0)
371
+
372
+ // for {
373
+ // i, ok := pageVisitStack.Pop()
374
+ // if !ok {
375
+ // break
376
+ // }
377
+ // if _, ok := pageTypes[i]; ok {
378
+ // d.Fatalf("page %d already visited", i)
379
+ // }
345
380
381
+ // sqlite3SeekPage(d, h, i)
382
+ // typ := d.U8()
383
+
384
+ // switch typ {
385
+ // case pageTypeBTreeIndexInterior,
386
+ // pageTypeBTreeTableInterior:
387
+
388
+ // d.U16() // start_free_blocks
389
+ // d.U16() // cell_start
390
+ // d.U8() // cell_fragments
391
+ // rightPointer := d.U32()
392
+
393
+ // pageCells := d.U16()
394
+ // for i := uint64(0); i < pageCells; i++ {
395
+
396
+ // }
397
+
398
+ // switch typ {
399
+ // case pageTypeBTreeIndexInterior:
400
+
401
+ // }
402
+
403
+ // default:
404
+ // d.Fatalf("asd")
405
+ // }
406
+
407
+ // }
408
+
409
+ // return nil
410
+
411
+ d .FieldArray ("pages" , func (d * decode.D ) {
346
412
// add a filler entry to make real pages start at index 1
347
413
d .FieldStruct ("page" , func (d * decode.D ) {
348
414
d .FieldValueStr ("type" , "page0_index_fill" )
349
415
})
350
416
417
+ // for {
418
+ // i, ok := pageStack.Pop()
419
+ // if !ok {
420
+ // break
421
+ // }
422
+ // if _, ok := pageSeen[i]; ok {
423
+ // d.Fatalf("page %d already visited", i)
424
+ // }
425
+ // pageSeen[i] = struct{}{}
426
+
351
427
for i := 0 ; i < h .databaseSizePages ; i ++ {
352
428
pageOffset := h .pageSize * int64 (i )
353
429
d .SeekAbs (pageOffset * 8 )
354
430
// skip header for first page
355
431
if i == 0 {
356
432
d .SeekRel (sqlite3HeaderSize * 8 )
357
433
}
434
+ sqlite3SeekPage (d , h , i )
358
435
359
436
d .FieldStruct ("page" , func (d * decode.D ) {
360
437
typ := d .FieldU8 ("type" , pageTypeMap )
@@ -413,18 +490,18 @@ func sqlite3Decode(d *decode.D, in interface{}) interface{} {
413
490
switch typ {
414
491
case pageTypeBTreeIndexInterior :
415
492
d .FieldU32 ("left_child" )
416
- payLoadLen := d .FieldSFn ("payload_len" , varintDecode )
493
+ payLoadLen := d .FieldSintFn ("payload_len" , varintDecode )
417
494
// formula for x from sqlite format spec
418
495
sqlite3DecodeTreePage (d , h , ((h .pageSize - 12 )* 64 / 255 )- 23 , payLoadLen )
419
496
case pageTypeBTreeTableInterior :
420
497
d .FieldU32 ("left_child" )
421
- d .FieldSFn ("rowid" , varintDecode )
498
+ d .FieldSintFn ("rowid" , varintDecode )
422
499
case pageTypeBTreeIndexLeaf :
423
- payLoadLen := d .FieldSFn ("payload_len" , varintDecode )
500
+ payLoadLen := d .FieldSintFn ("payload_len" , varintDecode )
424
501
sqlite3DecodeTreePage (d , h , ((h .pageSize - 12 )* 64 / 255 )- 23 , payLoadLen )
425
502
case pageTypeBTreeTableLeaf :
426
- payLoadLen := d .FieldSFn ("payload_len" , varintDecode )
427
- d .FieldSFn ("rowid" , varintDecode )
503
+ payLoadLen := d .FieldSintFn ("payload_len" , varintDecode )
504
+ d .FieldSintFn ("rowid" , varintDecode )
428
505
sqlite3DecodeTreePage (d , h , h .pageSize - 35 , payLoadLen )
429
506
}
430
507
})
0 commit comments