@@ -41,25 +41,40 @@ import (
4141 "embed"
4242
4343 "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"
4645 "github.com/wader/fq/pkg/bitio"
4746 "github.com/wader/fq/pkg/decode"
47+ "github.com/wader/fq/pkg/interp"
4848 "github.com/wader/fq/pkg/scalar"
4949)
5050
5151//go:embed *.jq
5252var sqlite3FS embed.FS
5353
5454func init () {
55- registry . MustRegister (decode.Format {
55+ interp . RegisterFormat (decode.Format {
5656 Name : format .SQLITE3 ,
5757 Description : "SQLite v3 database" ,
5858 Groups : []string {format .PROBE },
5959 DecodeFn : sqlite3Decode ,
6060 Functions : []string {"torepr" },
61- Files : sqlite3FS ,
6261 })
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
6378}
6479
6580const sqlite3HeaderSize = 100
@@ -79,7 +94,7 @@ const (
7994 serialTypeInternal11 = 11
8095)
8196
82- var serialTypeMap = scalar.SToSymStr {
97+ var serialTypeMap = scalar.UintMapSymStr {
8398 serialTypeNULL : "null" ,
8499 serialTypeS8 : "int8" ,
85100 serialTypeSBE16 : "int16" ,
@@ -94,8 +109,8 @@ var serialTypeMap = scalar.SToSymStr{
94109 serialTypeInternal11 : "internal11" ,
95110}
96111
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 )
99114 if st , ok := serialTypeMap [typ ]; ok {
100115 s .Description = st
101116 } else if typ >= 12 && typ % 2 == 0 {
@@ -106,23 +121,25 @@ var serialTypeMapper = scalar.Fn(func(s scalar.S) (scalar.S, error) {
106121 return s , nil
107122})
108123
124+ type pageType int
125+
109126const (
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
115132)
116133
117- var pageTypeMap = scalar.UToSymStr {
134+ var pageTypeMap = scalar.UintMapSymStr {
118135 // pageTypePtrmap: "ptrmap",
119136 pageTypeBTreeIndexInterior : "index_interior" ,
120137 pageTypeBTreeTableInterior : "table_interior" ,
121138 pageTypeBTreeIndexLeaf : "index_leaf" ,
122139 pageTypeBTreeTableLeaf : "table_leaf" ,
123140}
124141
125- var ptrmapTypeMap = scalar.UToSymStr {
142+ var ptrmapTypeMap = scalar.UintMapSymStr {
126143 1 : "rootpage" ,
127144 2 : "freepage" ,
128145 3 : "overflow1" ,
@@ -136,13 +153,13 @@ const (
136153 textEncodingUTF16BE = 3
137154)
138155
139- var textEncodingMap = scalar.UToSymStr {
156+ var textEncodingMap = scalar.UintMapSymStr {
140157 textEncodingUTF8 : "utf8" ,
141158 textEncodingUTF16LE : "utf16le" ,
142159 textEncodingUTF16BE : "utf16be" ,
143160}
144161
145- var versionMap = scalar.UToSymStr {
162+ var versionMap = scalar.UintMapSymStr {
146163 1 : "legacy" ,
147164 2 : "wal" ,
148165}
@@ -164,13 +181,13 @@ func varintDecode(d *decode.D) int64 {
164181 break
165182 }
166183 }
167- return mathextra .TwosComplement (64 , n )
184+ return mathex .TwosComplement (64 , n )
168185}
169186
170187func sqlite3DecodeSerialType (d * decode.D , h sqlite3Header , typ int64 ) {
171188 switch typ {
172189 case serialTypeNULL :
173- d .FieldValueNil ("value" )
190+ d .FieldValueAny ("value" , nil )
174191 case serialTypeS8 :
175192 d .FieldS8 ("value" )
176193 case serialTypeSBE16 :
@@ -186,9 +203,9 @@ func sqlite3DecodeSerialType(d *decode.D, h sqlite3Header, typ int64) {
186203 case serialTypeFloatBE64 :
187204 d .FieldF64 ("value" )
188205 case serialTypeInteger0 :
189- d .FieldValueU ("value" , 0 )
206+ d .FieldValueAny ("value" , 0 )
190207 case serialTypeInteger1 :
191- d .FieldValueU ("value" , 1 )
208+ d .FieldValueAny ("value" , 1 )
192209 case 10 , 11 :
193210 // internal, should not appear in wellformed file
194211 default :
@@ -228,15 +245,15 @@ func sqlite3DecodeCellFreeblock(d *decode.D) uint64 {
228245
229246func sqlite3CellPayloadDecode (d * decode.D , h sqlite3Header ) {
230247 lengthStart := d .Pos ()
231- length := d .FieldSFn ("length" , varintDecode )
248+ length := d .FieldSintFn ("length" , varintDecode )
232249 lengthBits := d .Pos () - lengthStart
233250 var serialTypes []int64
234251 d .FramedFn ((length )* 8 - lengthBits , func (d * decode.D ) {
235252 d .FieldArray ("serials" , func (d * decode.D ) {
236253 for ! d .End () {
237254 serialTypes = append (
238255 serialTypes ,
239- d .FieldSFn ("serial" , varintDecode , serialTypeMapper ),
256+ d .FieldSintFn ("serial" , varintDecode , serialTypeMapper ),
240257 )
241258 }
242259 })
@@ -276,18 +293,18 @@ func sqlite3DecodeTreePage(d *decode.D, h sqlite3Header, x int64, payLoadLen int
276293 d .FieldStruct ("overflow_page" , func (d * decode.D ) {
277294 br := d .FieldRawLen ("data" , firstPayLoadLen * 8 )
278295 nextPage = d .FieldS32 ("next_page" )
279- d .MustCopyBits (payLoadBB , br )
296+ d .CopyBits (payLoadBB , br )
280297 })
281298
282299 payLoadLenLeft := payLoadLen - firstPayLoadLen
283300 for nextPage != 0 {
284301 d .SeekAbs (((nextPage - 1 ) * h .pageSize ) * 8 )
285302 d .FieldStruct ("overflow_page" , func (d * decode.D ) {
286303 nextPage = d .FieldS32 ("next_page" )
287- overflowSize := mathextra . MinInt64 (h .pageSize - 4 , payLoadLenLeft )
304+ overflowSize := mathex . Min (h .pageSize - 4 , payLoadLenLeft )
288305 br := d .FieldRawLen ("data" , overflowSize * 8 )
289306 payLoadLenLeft -= overflowSize
290- d .MustCopyBits (payLoadBB , br )
307+ d .CopyBits (payLoadBB , br )
291308 })
292309 }
293310 })
@@ -299,26 +316,34 @@ func sqlite3DecodeTreePage(d *decode.D, h sqlite3Header, x int64, payLoadLen int
299316 }
300317}
301318
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+
302327func sqlite3Decode (d * decode.D , in interface {}) interface {} {
303328 var h sqlite3Header
304329
305330 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.
322347 textEncoding := int (d .FieldU32 ("text_encoding" , textEncodingMap ))
323348 d .FieldU32 ("user_version" ) // " as read and set by the user_version pragma.
324349 d .FieldU32 ("incremental_vacuum_mode" ) // False (zero) otherwise.
@@ -328,9 +353,9 @@ func sqlite3Decode(d *decode.D, in interface{}) interface{} {
328353 d .FieldU32 ("sqlite_version_number" ) //
329354
330355 // TODO: nicer API for fallback?
331- pageSize := int64 (pageSizeS .ActualU () )
356+ pageSize := int64 (pageSizeS .Actual )
332357 if pageSizeS .Sym != nil {
333- pageSize = int64 (pageSizeS .SymU ())
358+ pageSize = int64 (pageSizeS .SymUint ())
334359 }
335360
336361 h = sqlite3Header {
@@ -340,21 +365,73 @@ func sqlite3Decode(d *decode.D, in interface{}) interface{} {
340365 }
341366 })
342367
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+ // }
345380
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 ) {
346412 // add a filler entry to make real pages start at index 1
347413 d .FieldStruct ("page" , func (d * decode.D ) {
348414 d .FieldValueStr ("type" , "page0_index_fill" )
349415 })
350416
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+
351427 for i := 0 ; i < h .databaseSizePages ; i ++ {
352428 pageOffset := h .pageSize * int64 (i )
353429 d .SeekAbs (pageOffset * 8 )
354430 // skip header for first page
355431 if i == 0 {
356432 d .SeekRel (sqlite3HeaderSize * 8 )
357433 }
434+ sqlite3SeekPage (d , h , i )
358435
359436 d .FieldStruct ("page" , func (d * decode.D ) {
360437 typ := d .FieldU8 ("type" , pageTypeMap )
@@ -413,18 +490,18 @@ func sqlite3Decode(d *decode.D, in interface{}) interface{} {
413490 switch typ {
414491 case pageTypeBTreeIndexInterior :
415492 d .FieldU32 ("left_child" )
416- payLoadLen := d .FieldSFn ("payload_len" , varintDecode )
493+ payLoadLen := d .FieldSintFn ("payload_len" , varintDecode )
417494 // formula for x from sqlite format spec
418495 sqlite3DecodeTreePage (d , h , ((h .pageSize - 12 )* 64 / 255 )- 23 , payLoadLen )
419496 case pageTypeBTreeTableInterior :
420497 d .FieldU32 ("left_child" )
421- d .FieldSFn ("rowid" , varintDecode )
498+ d .FieldSintFn ("rowid" , varintDecode )
422499 case pageTypeBTreeIndexLeaf :
423- payLoadLen := d .FieldSFn ("payload_len" , varintDecode )
500+ payLoadLen := d .FieldSintFn ("payload_len" , varintDecode )
424501 sqlite3DecodeTreePage (d , h , ((h .pageSize - 12 )* 64 / 255 )- 23 , payLoadLen )
425502 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 )
428505 sqlite3DecodeTreePage (d , h , h .pageSize - 35 , payLoadLen )
429506 }
430507 })
0 commit comments