Skip to content

Commit

Permalink
Lines delimiter.
Browse files Browse the repository at this point in the history
  • Loading branch information
ncruces committed Jan 5, 2025
1 parent c3633dd commit f7c3fb8
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 26 deletions.
28 changes: 12 additions & 16 deletions ext/closure/closure.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,11 @@ func (c *closure) BestIndex(idx *sqlite3.IndexInfo) error {
cost := 1e7

for i, cst := range idx.Constraint {
if !cst.Usable {
switch {
case !cst.Usable:
continue
}
if plan&1 == 0 && cst.Column == _COL_ROOT {

case plan&1 == 0 && cst.Column == _COL_ROOT:
switch cst.Op {
case sqlite3.INDEX_CONSTRAINT_EQ:
plan |= 1
Expand All @@ -97,9 +98,8 @@ func (c *closure) BestIndex(idx *sqlite3.IndexInfo) error {
Omit: true,
}
}
continue
}
if plan&0xf0 == 0 && cst.Column == _COL_DEPTH {

case plan&0xf0 == 0 && cst.Column == _COL_DEPTH:
switch cst.Op {
case sqlite3.INDEX_CONSTRAINT_LT, sqlite3.INDEX_CONSTRAINT_LE, sqlite3.INDEX_CONSTRAINT_EQ:
plan |= posi << 4
Expand All @@ -110,9 +110,8 @@ func (c *closure) BestIndex(idx *sqlite3.IndexInfo) error {
plan |= 2
}
}
continue
}
if plan&0xf00 == 0 && cst.Column == _COL_TABLENAME {

case plan&0xf00 == 0 && cst.Column == _COL_TABLENAME:
switch cst.Op {
case sqlite3.INDEX_CONSTRAINT_EQ:
plan |= posi << 8
Expand All @@ -123,9 +122,8 @@ func (c *closure) BestIndex(idx *sqlite3.IndexInfo) error {
Omit: true,
}
}
continue
}
if plan&0xf000 == 0 && cst.Column == _COL_IDCOLUMN {

case plan&0xf000 == 0 && cst.Column == _COL_IDCOLUMN:
switch cst.Op {
case sqlite3.INDEX_CONSTRAINT_EQ:
plan |= posi << 12
Expand All @@ -135,9 +133,8 @@ func (c *closure) BestIndex(idx *sqlite3.IndexInfo) error {
Omit: true,
}
}
continue
}
if plan&0xf0000 == 0 && cst.Column == _COL_PARENTCOLUMN {

case plan&0xf0000 == 0 && cst.Column == _COL_PARENTCOLUMN:
switch cst.Op {
case sqlite3.INDEX_CONSTRAINT_EQ:
plan |= posi << 16
Expand All @@ -147,7 +144,6 @@ func (c *closure) BestIndex(idx *sqlite3.IndexInfo) error {
Omit: true,
}
}
continue
}
}

Expand Down
52 changes: 43 additions & 9 deletions ext/lines/lines.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ func RegisterFS(db *sqlite3.Conn, fsys fs.FS) error {
return errors.Join(
sqlite3.CreateModule(db, "lines", nil,
func(db *sqlite3.Conn, _, _, _ string, _ ...string) (lines, error) {
err := db.DeclareVTab(`CREATE TABLE x(line TEXT, data HIDDEN)`)
err := db.DeclareVTab(`CREATE TABLE x(line TEXT, data HIDDEN, delim HIDDEN)`)
if err == nil {
err = db.VTabConfig(sqlite3.VTAB_INNOCUOUS)
}
return lines{}, err
}),
sqlite3.CreateModule(db, "lines_read", nil,
func(db *sqlite3.Conn, _, _, _ string, _ ...string) (lines, error) {
err := db.DeclareVTab(`CREATE TABLE x(line TEXT, data HIDDEN)`)
err := db.DeclareVTab(`CREATE TABLE x(line TEXT, data HIDDEN, delim HIDDEN)`)
if err == nil {
err = db.VTabConfig(sqlite3.VTAB_DIRECTONLY)
}
Expand All @@ -58,19 +58,29 @@ type lines struct {
fsys fs.FS
}

func (l lines) BestIndex(idx *sqlite3.IndexInfo) error {
func (l lines) BestIndex(idx *sqlite3.IndexInfo) (err error) {
err = sqlite3.CONSTRAINT
for i, cst := range idx.Constraint {
if cst.Column == 1 && cst.Op == sqlite3.INDEX_CONSTRAINT_EQ && cst.Usable {
if !cst.Usable || cst.Op != sqlite3.INDEX_CONSTRAINT_EQ {
continue
}
switch cst.Column {
case 1:
idx.ConstraintUsage[i] = sqlite3.IndexConstraintUsage{
Omit: true,
ArgvIndex: 1,
}
idx.EstimatedCost = 1e6
idx.EstimatedRows = 100
return nil
err = nil
case 2:
idx.ConstraintUsage[i] = sqlite3.IndexConstraintUsage{
Omit: true,
ArgvIndex: 2,
}
}
}
return sqlite3.CONSTRAINT
return err
}

func (l lines) Open() (sqlite3.VTabCursor, error) {
Expand All @@ -85,6 +95,7 @@ type cursor struct {
line []byte
rowID int64
eof bool
delim byte
}

func (c *cursor) EOF() bool {
Expand Down Expand Up @@ -140,6 +151,15 @@ func (c *reader) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
return fmt.Errorf("lines: unsupported argument:%.0w %v", sqlite3.MISMATCH, typ)
}

c.delim = '\n'
if len(arg) > 1 {
b := arg[1].RawText()
if len(b) != 1 {
return fmt.Errorf("lines: delimiter must be a single byte%.0w", sqlite3.MISMATCH)
}
c.delim = b[0]
}

c.reader = bufio.NewReader(r)
c.closer, _ = r.(io.Closer)
c.rowID = 0
Expand All @@ -150,7 +170,12 @@ func (c *reader) Next() (err error) {
c.line = c.line[:0]
for more := true; more; {
var line []byte
line, more, err = c.reader.ReadLine()
if c.delim == '\n' {
line, more, err = c.reader.ReadLine()
} else {
line, err = c.reader.ReadSlice(c.delim)
more = err == bufio.ErrBufferFull
}
c.line = append(c.line, line...)
}
if err == io.EOF {
Expand All @@ -177,18 +202,27 @@ func (c *buffer) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
return fmt.Errorf("lines: unsupported argument:%.0w %v", sqlite3.MISMATCH, typ)
}

c.delim = '\n'
if len(arg) > 1 {
b := arg[1].RawText()
if len(b) != 1 {
return fmt.Errorf("lines: delimiter must be a single byte%.0w", sqlite3.MISMATCH)
}
c.delim = b[0]
}

c.rowID = 0
return c.Next()
}

func (c *buffer) Next() error {
i := bytes.IndexByte(c.data, '\n')
i := bytes.IndexByte(c.data, c.delim)
j := i + 1
switch {
case i < 0:
i = len(c.data)
j = i
case i > 0 && c.data[i-1] == '\r':
case i > 0 && c.delim == '\n' && c.data[i-1] == '\r':
i--
}
c.eof = len(c.data) == 0
Expand Down
2 changes: 1 addition & 1 deletion ext/lines/lines_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func Test_lines_test(t *testing.T) {
}
defer db.Close()

rows, err := db.Query(`SELECT rowid, line FROM lines_read(?)`, "lines_test.go")
rows, err := db.Query(`SELECT rowid, line FROM lines_read(?, '}')`, "lines_test.go")
if errors.Is(err, os.ErrNotExist) {
t.Skip(err)
}
Expand Down

0 comments on commit f7c3fb8

Please sign in to comment.