Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
wader committed Aug 18, 2022
1 parent 6e293c2 commit d461d07
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 1,102 deletions.
97 changes: 88 additions & 9 deletions format/sqlite3/sqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@ import (
"embed"

"github.com/wader/fq/format"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/internal/mathextra"
"github.com/wader/fq/pkg/bitio"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/interp"
"github.com/wader/fq/pkg/scalar"
)

//go:embed *.jq
var sqlite3FS embed.FS

func init() {
registry.MustRegister(decode.Format{
interp.RegisterFormat(decode.Format{
Name: format.SQLITE3,
Description: "SQLite v3 database",
Groups: []string{format.PROBE},
Expand All @@ -62,6 +62,21 @@ func init() {
})
}

type intStack struct {
s []int
}

func (s *intStack) Push(n int) { s.s = append(s.s, n) }

func (s *intStack) Pop() (int, bool) {
if len(s.s) == 0 {
return 0, false
}
var n int
n, s.s = s.s[0], s.s[1:]
return n, true
}

const sqlite3HeaderSize = 100

const (
Expand Down Expand Up @@ -106,12 +121,14 @@ var serialTypeMapper = scalar.Fn(func(s scalar.S) (scalar.S, error) {
return s, nil
})

type pageType int

const (
pageTypePtrmap = 0x00
pageTypeBTreeIndexInterior = 0x02
pageTypeBTreeTableInterior = 0x05
pageTypeBTreeIndexLeaf = 0x0a
pageTypeBTreeTableLeaf = 0x0d
pageTypePtrmap pageType = 0x00
pageTypeBTreeIndexInterior = 0x02
pageTypeBTreeTableInterior = 0x05
pageTypeBTreeIndexLeaf = 0x0a
pageTypeBTreeTableLeaf = 0x0d
)

var pageTypeMap = scalar.UToSymStr{
Expand Down Expand Up @@ -276,7 +293,7 @@ func sqlite3DecodeTreePage(d *decode.D, h sqlite3Header, x int64, payLoadLen int
d.FieldStruct("overflow_page", func(d *decode.D) {
br := d.FieldRawLen("data", firstPayLoadLen*8)
nextPage = d.FieldS32("next_page")
d.MustCopyBits(payLoadBB, br)
d.CopyBits(payLoadBB, br)
})

payLoadLenLeft := payLoadLen - firstPayLoadLen
Expand All @@ -287,7 +304,7 @@ func sqlite3DecodeTreePage(d *decode.D, h sqlite3Header, x int64, payLoadLen int
overflowSize := mathextra.MinInt64(h.pageSize-4, payLoadLenLeft)
br := d.FieldRawLen("data", overflowSize*8)
payLoadLenLeft -= overflowSize
d.MustCopyBits(payLoadBB, br)
d.CopyBits(payLoadBB, br)
})
}
})
Expand All @@ -299,6 +316,14 @@ func sqlite3DecodeTreePage(d *decode.D, h sqlite3Header, x int64, payLoadLen int
}
}

func sqlite3SeekPage(d *decode.D, h sqlite3Header, i int) {
pageOffset := h.pageSize * int64(i)
if i == 0 {
pageOffset += sqlite3HeaderSize
}
d.SeekAbs(pageOffset * 8)
}

func sqlite3Decode(d *decode.D, in interface{}) interface{} {
var h sqlite3Header

Expand Down Expand Up @@ -340,6 +365,49 @@ func sqlite3Decode(d *decode.D, in interface{}) interface{} {
}
})

// pageTypes := map[int]pageType{}
// pageVisitStack := &intStack{}
// pageVisitStack.Push(0)

// for {
// i, ok := pageVisitStack.Pop()
// if !ok {
// break
// }
// if _, ok := pageTypes[i]; ok {
// d.Fatalf("page %d already visited", i)
// }

// sqlite3SeekPage(d, h, i)
// typ := d.U8()

// switch typ {
// case pageTypeBTreeIndexInterior,
// pageTypeBTreeTableInterior:

// d.U16() // start_free_blocks
// d.U16() // cell_start
// d.U8() // cell_fragments
// rightPointer := d.U32()

// pageCells := d.U16()
// for i := uint64(0); i < pageCells; i++ {

// }

// switch typ {
// case pageTypeBTreeIndexInterior:

// }

// default:
// d.Fatalf("asd")
// }

// }

// return nil

d.FieldArray("pages", func(d *decode.D) {
d.RangeSorted = false

Expand All @@ -348,13 +416,24 @@ func sqlite3Decode(d *decode.D, in interface{}) interface{} {
d.FieldValueStr("type", "page0_index_fill")
})

// for {
// i, ok := pageStack.Pop()
// if !ok {
// break
// }
// if _, ok := pageSeen[i]; ok {
// d.Fatalf("page %d already visited", i)
// }
// pageSeen[i] = struct{}{}

for i := 0; i < h.databaseSizePages; i++ {
pageOffset := h.pageSize * int64(i)
d.SeekAbs(pageOffset * 8)
// skip header for first page
if i == 0 {
d.SeekRel(sqlite3HeaderSize * 8)
}
sqlite3SeekPage(d, h, i)

d.FieldStruct("page", func(d *decode.D) {
typ := d.FieldU8("type", pageTypeMap)
Expand Down
12 changes: 6 additions & 6 deletions format/sqlite3/testdata/multi_tables.sql
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
CREATE TABLE aaa (
cint int primary key,
ctext text
cint INT PRIMARY KEY,
ctext TEXT
);
INSERT INTO aaa VALUES(123, "AAAAAAA");

CREATE TABLE bbb (
cint int primary key,
ctext text
cint INT PRIMARY KEY,
ctext TEXT
);
INSERT INTO bbb VALUES(456, "BBBBBBB");

CREATE TABLE ccc (
cint int primary key,
ctext text
cint INT PRIMARY KEY,
ctext TEXT
);
INSERT INTO ccc VALUES(789, "CCCCCCC");
Binary file modified format/sqlite3/testdata/multi_tables.sql.db
Binary file not shown.
Loading

0 comments on commit d461d07

Please sign in to comment.