vendor: Update everything
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4620
This commit is contained in:
41
vendor/github.com/cznic/b/btree.go
generated
vendored
41
vendor/github.com/cznic/b/btree.go
generated
vendored
@@ -301,7 +301,6 @@ func (t *Tree) Delete(k interface{} /*K*/) (ok bool) {
|
||||
pi = i + 1
|
||||
p = x
|
||||
q = x.x[pi].ch
|
||||
ok = false
|
||||
continue
|
||||
case *d:
|
||||
t.extract(x, i)
|
||||
@@ -547,12 +546,13 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
|
||||
if ok {
|
||||
switch x := q.(type) {
|
||||
case *x:
|
||||
i++
|
||||
if x.c > 2*kx {
|
||||
x, i = t.splitX(p, x, pi, i)
|
||||
}
|
||||
pi = i + 1
|
||||
pi = i
|
||||
p = x
|
||||
q = x.x[i+1].ch
|
||||
q = x.x[i].ch
|
||||
continue
|
||||
case *d:
|
||||
x.d[i].v = v
|
||||
@@ -614,12 +614,13 @@ func (t *Tree) Put(k interface{} /*K*/, upd func(oldV interface{} /*V*/, exists
|
||||
if ok {
|
||||
switch x := q.(type) {
|
||||
case *x:
|
||||
i++
|
||||
if x.c > 2*kx {
|
||||
x, i = t.splitX(p, x, pi, i)
|
||||
}
|
||||
pi = i + 1
|
||||
pi = i
|
||||
p = x
|
||||
q = x.x[i+1].ch
|
||||
q = x.x[i].ch
|
||||
continue
|
||||
case *d:
|
||||
oldV = x.d[i].v
|
||||
@@ -701,36 +702,20 @@ func (t *Tree) splitX(p *x, q *x, pi int, i int) (*x, int) {
|
||||
r.c = kx
|
||||
if pi >= 0 {
|
||||
p.insert(pi, q.x[kx].k, r)
|
||||
q.x[kx].k = zk
|
||||
for i := range q.x[kx+1:] {
|
||||
q.x[kx+i+1] = zxe
|
||||
}
|
||||
|
||||
switch {
|
||||
case i < kx:
|
||||
return q, i
|
||||
case i == kx:
|
||||
return p, pi
|
||||
default: // i > kx
|
||||
return r, i - kx - 1
|
||||
}
|
||||
} else {
|
||||
t.r = newX(q).insert(0, q.x[kx].k, r)
|
||||
}
|
||||
|
||||
nr := newX(q).insert(0, q.x[kx].k, r)
|
||||
t.r = nr
|
||||
q.x[kx].k = zk
|
||||
for i := range q.x[kx+1:] {
|
||||
q.x[kx+i+1] = zxe
|
||||
}
|
||||
|
||||
switch {
|
||||
case i < kx:
|
||||
return q, i
|
||||
case i == kx:
|
||||
return nr, 0
|
||||
default: // i > kx
|
||||
return r, i - kx - 1
|
||||
if i > kx {
|
||||
q = r
|
||||
i -= kx + 1
|
||||
}
|
||||
|
||||
return q, i
|
||||
}
|
||||
|
||||
func (t *Tree) underflow(p *x, q *d, pi int) {
|
||||
|
||||
79
vendor/github.com/cznic/b/example/int.go
generated
vendored
79
vendor/github.com/cznic/b/example/int.go
generated
vendored
@@ -76,7 +76,7 @@ type (
|
||||
//
|
||||
// However, once an Enumerator returns io.EOF to signal "no more
|
||||
// items", it does no more attempt to "resync" on tree mutation(s). In
|
||||
// other words, io.EOF from an Enumaretor is "sticky" (idempotent).
|
||||
// other words, io.EOF from an Enumerator is "sticky" (idempotent).
|
||||
Enumerator struct {
|
||||
err error
|
||||
hit bool
|
||||
@@ -450,7 +450,7 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k int, v int) {
|
||||
t.ver++
|
||||
l, r := p.siblings(pi)
|
||||
|
||||
if l != nil && l.c < 2*kd {
|
||||
if l != nil && l.c < 2*kd && i != 0 {
|
||||
l.mvL(q, 1)
|
||||
t.insert(q, i-1, k, v)
|
||||
p.x[pi-1].k = q.d[0].k
|
||||
@@ -473,9 +473,9 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k int, v int) {
|
||||
t.split(p, q, pi, i, k, v)
|
||||
}
|
||||
|
||||
// Seek returns an Enumerator positioned on a an item such that k >= item's
|
||||
// key. ok reports if k == item.key The Enumerator's position is possibly
|
||||
// after the last item in the tree.
|
||||
// Seek returns an Enumerator positioned on an item such that k >= item's key.
|
||||
// ok reports if k == item.key The Enumerator's position is possibly after the
|
||||
// last item in the tree.
|
||||
func (t *Tree) Seek(k int) (e *Enumerator, ok bool) {
|
||||
q := t.r
|
||||
if q == nil {
|
||||
@@ -547,12 +547,13 @@ func (t *Tree) Set(k int, v int) {
|
||||
if ok {
|
||||
switch x := q.(type) {
|
||||
case *x:
|
||||
i++
|
||||
if x.c > 2*kx {
|
||||
x, i = t.splitX(p, x, pi, i)
|
||||
}
|
||||
pi = i + 1
|
||||
pi = i
|
||||
p = x
|
||||
q = x.x[i+1].ch
|
||||
q = x.x[i].ch
|
||||
continue
|
||||
case *d:
|
||||
x.d[i].v = v
|
||||
@@ -614,12 +615,13 @@ func (t *Tree) Put(k int, upd func(oldV int, exists bool) (newV int, write bool)
|
||||
if ok {
|
||||
switch x := q.(type) {
|
||||
case *x:
|
||||
i++
|
||||
if x.c > 2*kx {
|
||||
x, i = t.splitX(p, x, pi, i)
|
||||
}
|
||||
pi = i + 1
|
||||
pi = i
|
||||
p = x
|
||||
q = x.x[i+1].ch
|
||||
q = x.x[i].ch
|
||||
continue
|
||||
case *d:
|
||||
oldV = x.d[i].v
|
||||
@@ -701,36 +703,20 @@ func (t *Tree) splitX(p *x, q *x, pi int, i int) (*x, int) {
|
||||
r.c = kx
|
||||
if pi >= 0 {
|
||||
p.insert(pi, q.x[kx].k, r)
|
||||
q.x[kx].k = zk
|
||||
for i := range q.x[kx+1:] {
|
||||
q.x[kx+i+1] = zxe
|
||||
}
|
||||
|
||||
switch {
|
||||
case i < kx:
|
||||
return q, i
|
||||
case i == kx:
|
||||
return p, pi
|
||||
default: // i > kx
|
||||
return r, i - kx - 1
|
||||
}
|
||||
} else {
|
||||
t.r = newX(q).insert(0, q.x[kx].k, r)
|
||||
}
|
||||
|
||||
nr := newX(q).insert(0, q.x[kx].k, r)
|
||||
t.r = nr
|
||||
q.x[kx].k = zk
|
||||
for i := range q.x[kx+1:] {
|
||||
q.x[kx+i+1] = zxe
|
||||
}
|
||||
|
||||
switch {
|
||||
case i < kx:
|
||||
return q, i
|
||||
case i == kx:
|
||||
return nr, 0
|
||||
default: // i > kx
|
||||
return r, i - kx - 1
|
||||
if i > kx {
|
||||
q = r
|
||||
i -= kx + 1
|
||||
}
|
||||
|
||||
return q, i
|
||||
}
|
||||
|
||||
func (t *Tree) underflow(p *x, q *d, pi int) {
|
||||
@@ -826,13 +812,7 @@ func (e *Enumerator) Next() (k int, v int, err error) {
|
||||
}
|
||||
|
||||
if e.ver != e.t.ver {
|
||||
f, hit := e.t.Seek(e.k)
|
||||
if !e.hit && hit {
|
||||
if err = f.next(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
f, _ := e.t.Seek(e.k)
|
||||
*e = *f
|
||||
f.Close()
|
||||
}
|
||||
@@ -849,7 +829,7 @@ func (e *Enumerator) Next() (k int, v int, err error) {
|
||||
|
||||
i := e.q.d[e.i]
|
||||
k, v = i.k, i.v
|
||||
e.k, e.hit = k, false
|
||||
e.k, e.hit = k, true
|
||||
e.next()
|
||||
return
|
||||
}
|
||||
@@ -880,13 +860,7 @@ func (e *Enumerator) Prev() (k int, v int, err error) {
|
||||
}
|
||||
|
||||
if e.ver != e.t.ver {
|
||||
f, hit := e.t.Seek(e.k)
|
||||
if !e.hit && hit {
|
||||
if err = f.prev(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
f, _ := e.t.Seek(e.k)
|
||||
*e = *f
|
||||
f.Close()
|
||||
}
|
||||
@@ -895,15 +869,22 @@ func (e *Enumerator) Prev() (k int, v int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if !e.hit {
|
||||
// move to previous because Seek overshoots if there's no hit
|
||||
if err = e.prev(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if e.i >= e.q.c {
|
||||
if err = e.next(); err != nil {
|
||||
if err = e.prev(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
i := e.q.d[e.i]
|
||||
k, v = i.k, i.v
|
||||
e.k, e.hit = k, false
|
||||
e.k, e.hit = k, true
|
||||
e.prev()
|
||||
return
|
||||
}
|
||||
|
||||
2
vendor/github.com/cznic/fileutil/fileutil.go
generated
vendored
2
vendor/github.com/cznic/fileutil/fileutil.go
generated
vendored
@@ -190,7 +190,9 @@ func TempFile(dir, prefix, suffix string) (f *os.File, err error) {
|
||||
f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
|
||||
if os.IsExist(err) {
|
||||
if nconflict++; nconflict > 10 {
|
||||
randmu.Lock()
|
||||
rand = reseed()
|
||||
randmu.Unlock()
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
27
vendor/github.com/cznic/golex/lex/LICENSE
generated
vendored
Normal file
27
vendor/github.com/cznic/golex/lex/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2014 The golex Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the names of the authors nor the names of the
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
410
vendor/github.com/cznic/golex/lex/api.go
generated
vendored
Normal file
410
vendor/github.com/cznic/golex/lex/api.go
generated
vendored
Normal file
@@ -0,0 +1,410 @@
|
||||
// Copyright (c) 2015 The golex Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package lex
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// BOM handling modes which can be set by the BOMMode Option. Default is BOMIgnoreFirst.
|
||||
const (
|
||||
BOMError = iota // BOM is an error anywhere.
|
||||
BOMIgnoreFirst // Skip BOM if at beginning, report as error if anywhere else.
|
||||
BOMPassAll // No special handling of BOM.
|
||||
BOMPassFirst // No special handling of BOM if at beginning, report as error if anywhere else.
|
||||
)
|
||||
|
||||
const (
|
||||
NonASCII = 0x80 // DefaultRuneClass returns NonASCII for non ASCII runes.
|
||||
RuneEOF = -1 // Distinct from any valid Unicode rune value.
|
||||
)
|
||||
|
||||
// DefaultRuneClass returns the character class of r. If r is an ASCII code
|
||||
// then its class equals the ASCII code. Any other rune is of class NonASCII.
|
||||
//
|
||||
// DefaultRuneClass is the default implementation Lexer will use to convert
|
||||
// runes (21 bit entities) to scanner classes (8 bit entities).
|
||||
//
|
||||
// Non ASCII aware lexical analyzers will typically use their own
|
||||
// categorization function. To assign such custom function use the RuneClass
|
||||
// option.
|
||||
func DefaultRuneClass(r rune) int {
|
||||
if r >= 0 && r < 0x80 {
|
||||
return int(r)
|
||||
}
|
||||
|
||||
return NonASCII
|
||||
}
|
||||
|
||||
// Char represents a rune and its position.
|
||||
type Char struct {
|
||||
Rune rune
|
||||
pos int32
|
||||
}
|
||||
|
||||
// NewChar returns a new Char value.
|
||||
func NewChar(pos token.Pos, r rune) Char { return Char{pos: int32(pos), Rune: r} }
|
||||
|
||||
// IsValid reports whether c is not a zero Char.
|
||||
func (c Char) IsValid() bool { return c.Pos().IsValid() }
|
||||
|
||||
// Pos returns the token.Pos associated with c.
|
||||
func (c Char) Pos() token.Pos { return token.Pos(c.pos) }
|
||||
|
||||
// CharReader is a RuneReader providing additionally explicit position
|
||||
// information by returning a Char instead of a rune as its first result.
|
||||
type CharReader interface {
|
||||
ReadChar() (c Char, size int, err error)
|
||||
}
|
||||
|
||||
// Lexer suports golex[0] generated lexical analyzers.
|
||||
type Lexer struct {
|
||||
File *token.File // The *token.File passed to New.
|
||||
First Char // First remembers the lookahead char when Rule0 was invoked.
|
||||
Last Char // Last remembers the last Char returned by Next.
|
||||
Prev Char // Prev remembers the Char previous to Last.
|
||||
bomMode int // See the BOM* constants.
|
||||
bytesBuf bytes.Buffer // Used by TokenBytes.
|
||||
charSrc CharReader // Lexer alternative input.
|
||||
classf func(rune) int //
|
||||
errorf func(token.Pos, string) //
|
||||
lookahead Char // Lookahead if non zero.
|
||||
mark int // Longest match marker.
|
||||
off int // Used for File.AddLine.
|
||||
src io.RuneReader // Lexer input.
|
||||
tokenBuf []Char // Lexeme collector.
|
||||
ungetBuf []Char // Unget buffer.
|
||||
}
|
||||
|
||||
// New returns a new *Lexer. The result can be amended using opts.
|
||||
//
|
||||
// Non Unicode Input
|
||||
//
|
||||
// To consume sources in other encodings and still have exact position
|
||||
// information, pass an io.RuneReader which returns the next input character
|
||||
// reencoded as an Unicode rune but returns the size (number of bytes used to
|
||||
// encode it) of the original character, not the size of its UTF-8
|
||||
// representation after converted to an Unicode rune. Size is the second
|
||||
// returned value of io.RuneReader.ReadRune method[4].
|
||||
//
|
||||
// When src optionally implements CharReader its ReadChar method is used
|
||||
// instead of io.ReadRune.
|
||||
func New(file *token.File, src io.RuneReader, opts ...Option) (*Lexer, error) {
|
||||
r := &Lexer{
|
||||
File: file,
|
||||
bomMode: BOMIgnoreFirst,
|
||||
classf: DefaultRuneClass,
|
||||
src: src,
|
||||
}
|
||||
if x, ok := src.(CharReader); ok {
|
||||
r.charSrc = x
|
||||
}
|
||||
r.errorf = r.defaultErrorf
|
||||
for _, o := range opts {
|
||||
if err := o(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Abort handles the situation when the scanner does not successfully recognize
|
||||
// any token or when an attempt to find the longest match "overruns" from an
|
||||
// accepting state only to never reach an accepting state again. In the first
|
||||
// case the scanner was never in an accepting state since last call to Rule0
|
||||
// and then (true, previousLookahead rune) is returned, effectively consuming a
|
||||
// single Char token, avoiding scanner stall. Otherwise there was at least one
|
||||
// accepting scanner state marked using Mark. In this case Abort rollbacks the
|
||||
// lexer state to the marked state and returns (false, 0). The scanner must
|
||||
// then execute a prescribed goto statement. For example:
|
||||
//
|
||||
// %yyc c
|
||||
// %yyn c = l.Next()
|
||||
// %yym l.Mark()
|
||||
//
|
||||
// %{
|
||||
// package foo
|
||||
//
|
||||
// import (...)
|
||||
//
|
||||
// type lexer struct {
|
||||
// *lex.Lexer
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// func newLexer(...) *lexer {
|
||||
// return &lexer{
|
||||
// lex.NewLexer(...),
|
||||
// ...
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func (l *lexer) scan() int {
|
||||
// c := l.Enter()
|
||||
// %}
|
||||
//
|
||||
// ... more lex defintions
|
||||
//
|
||||
// %%
|
||||
//
|
||||
// c = l.Rule0()
|
||||
//
|
||||
// ... lex rules
|
||||
//
|
||||
// %%
|
||||
//
|
||||
// if c, ok := l.Abort(); ok {
|
||||
// return c
|
||||
// }
|
||||
//
|
||||
// goto yyAction
|
||||
// }
|
||||
func (l *Lexer) Abort() (int, bool) {
|
||||
if l.mark >= 0 {
|
||||
if len(l.tokenBuf) > l.mark {
|
||||
l.Unget(l.lookahead)
|
||||
for i := len(l.tokenBuf) - 1; i >= l.mark; i-- {
|
||||
l.Unget(l.tokenBuf[i])
|
||||
}
|
||||
}
|
||||
l.tokenBuf = l.tokenBuf[:l.mark]
|
||||
return 0, false
|
||||
}
|
||||
|
||||
switch n := len(l.tokenBuf); n {
|
||||
case 0: // [] z
|
||||
c := l.lookahead
|
||||
l.Next()
|
||||
return int(c.Rune), true
|
||||
case 1: // [a] z
|
||||
return int(l.tokenBuf[0].Rune), true
|
||||
default: // [a, b, ...], z
|
||||
c := l.tokenBuf[0] // a
|
||||
l.Unget(l.lookahead) // z
|
||||
for i := n - 1; i > 1; i-- {
|
||||
l.Unget(l.tokenBuf[i]) // ...
|
||||
}
|
||||
l.lookahead = l.tokenBuf[1] // b
|
||||
l.tokenBuf = l.tokenBuf[:1]
|
||||
return int(c.Rune), true
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Lexer) class() int { return l.classf(l.lookahead.Rune) }
|
||||
|
||||
func (l *Lexer) defaultErrorf(pos token.Pos, msg string) {
|
||||
l.Error(fmt.Sprintf("%v: %v", l.File.Position(pos), msg))
|
||||
}
|
||||
|
||||
// Enter ensures the lexer has a valid lookahead Char and returns its class.
|
||||
// Typical use in an .l file
|
||||
//
|
||||
// func (l *lexer) scan() lex.Char {
|
||||
// c := l.Enter()
|
||||
// ...
|
||||
func (l *Lexer) Enter() int {
|
||||
if !l.lookahead.IsValid() {
|
||||
l.Next()
|
||||
}
|
||||
return l.class()
|
||||
}
|
||||
|
||||
// Error Implements yyLexer[2] by printing the msg to stderr.
|
||||
func (l *Lexer) Error(msg string) {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", msg)
|
||||
}
|
||||
|
||||
// Lookahead returns the current lookahead.
|
||||
func (l *Lexer) Lookahead() Char {
|
||||
if !l.lookahead.IsValid() {
|
||||
l.Next()
|
||||
}
|
||||
return l.lookahead
|
||||
}
|
||||
|
||||
// Mark records the current state of scanner as accepting. It implements the
|
||||
// golex macro %yym. Typical usage in an .l file:
|
||||
//
|
||||
// %yym l.Mark()
|
||||
func (l *Lexer) Mark() { l.mark = len(l.tokenBuf) }
|
||||
|
||||
func (l *Lexer) next() int {
|
||||
const bom = '\ufeff'
|
||||
|
||||
if c := l.lookahead; c.IsValid() {
|
||||
l.tokenBuf = append(l.tokenBuf, c)
|
||||
}
|
||||
if n := len(l.ungetBuf); n != 0 {
|
||||
l.lookahead = l.ungetBuf[n-1]
|
||||
l.ungetBuf = l.ungetBuf[:n-1]
|
||||
return l.class()
|
||||
}
|
||||
|
||||
if l.src == nil {
|
||||
return RuneEOF
|
||||
}
|
||||
|
||||
var r rune
|
||||
var sz int
|
||||
var err error
|
||||
var pos token.Pos
|
||||
var c Char
|
||||
again:
|
||||
off0 := l.off
|
||||
switch cs := l.charSrc; {
|
||||
case cs != nil:
|
||||
c, sz, err = cs.ReadChar()
|
||||
r = c.Rune
|
||||
pos = c.Pos()
|
||||
default:
|
||||
r, sz, err = l.src.ReadRune()
|
||||
pos = l.File.Pos(l.off)
|
||||
}
|
||||
l.off += sz
|
||||
if err != nil {
|
||||
l.src = nil
|
||||
r = RuneEOF
|
||||
if err != io.EOF {
|
||||
l.errorf(pos, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if r == bom {
|
||||
switch l.bomMode {
|
||||
default:
|
||||
fallthrough
|
||||
case BOMIgnoreFirst:
|
||||
if off0 != 0 {
|
||||
l.errorf(pos, "unicode (UTF-8) BOM in middle of file")
|
||||
}
|
||||
goto again
|
||||
case BOMPassAll:
|
||||
// nop
|
||||
case BOMPassFirst:
|
||||
if off0 != 0 {
|
||||
l.errorf(pos, "unicode (UTF-8) BOM in middle of file")
|
||||
goto again
|
||||
}
|
||||
case BOMError:
|
||||
switch {
|
||||
case off0 == 0:
|
||||
l.errorf(pos, "unicode (UTF-8) BOM at beginnig of file")
|
||||
default:
|
||||
l.errorf(pos, "unicode (UTF-8) BOM in middle of file")
|
||||
}
|
||||
goto again
|
||||
}
|
||||
}
|
||||
|
||||
l.lookahead = NewChar(pos, r)
|
||||
if r == '\n' {
|
||||
l.File.AddLine(l.off)
|
||||
}
|
||||
return l.class()
|
||||
}
|
||||
|
||||
// Next advances the scanner for one rune and returns the respective character
|
||||
// class of the new lookahead. Typical usage in an .l file:
|
||||
//
|
||||
// %yyn c = l.Next()
|
||||
func (l *Lexer) Next() int {
|
||||
l.Prev = l.Last
|
||||
r := l.next()
|
||||
l.Last = l.lookahead
|
||||
return r
|
||||
}
|
||||
|
||||
// Offset returns the current reading offset of the lexer's source.
|
||||
func (l *Lexer) Offset() int { return l.off }
|
||||
|
||||
// Rule0 initializes the scanner state before the attempt to recognize a token
|
||||
// starts. The token collecting buffer is cleared. Rule0 records the current
|
||||
// lookahead in l.First and returns its class. Typical usage in an .l file:
|
||||
//
|
||||
// ... lex definitions
|
||||
//
|
||||
// %%
|
||||
//
|
||||
// c := l.Rule0()
|
||||
//
|
||||
// first-pattern-regexp
|
||||
func (l *Lexer) Rule0() int {
|
||||
if !l.lookahead.IsValid() {
|
||||
l.Next()
|
||||
}
|
||||
l.First = l.lookahead
|
||||
l.mark = -1
|
||||
if len(l.tokenBuf) > 1<<18 { //DONE constant tuned
|
||||
l.tokenBuf = nil
|
||||
} else {
|
||||
l.tokenBuf = l.tokenBuf[:0]
|
||||
}
|
||||
return l.class()
|
||||
}
|
||||
|
||||
// Token returns the currently collected token chars. The result is R/O.
|
||||
func (l *Lexer) Token() []Char { return l.tokenBuf }
|
||||
|
||||
// TokenBytes returns the UTF-8 encoding of Token. If builder is not nil then
|
||||
// it's called instead to build the encoded token byte value into the buffer
|
||||
// passed to it.
|
||||
//
|
||||
// The Result is R/O.
|
||||
func (l *Lexer) TokenBytes(builder func(*bytes.Buffer)) []byte {
|
||||
if len(l.bytesBuf.Bytes()) < 1<<18 { //DONE constant tuned
|
||||
l.bytesBuf.Reset()
|
||||
} else {
|
||||
l.bytesBuf = bytes.Buffer{}
|
||||
}
|
||||
switch {
|
||||
case builder != nil:
|
||||
builder(&l.bytesBuf)
|
||||
default:
|
||||
for _, c := range l.Token() {
|
||||
l.bytesBuf.WriteRune(c.Rune)
|
||||
}
|
||||
}
|
||||
return l.bytesBuf.Bytes()
|
||||
}
|
||||
|
||||
// Unget unreads all chars in c.
|
||||
func (l *Lexer) Unget(c ...Char) {
|
||||
l.ungetBuf = append(l.ungetBuf, c...)
|
||||
l.lookahead = Char{} // Must invalidate lookahead.
|
||||
}
|
||||
|
||||
// Option is a function which can be passed as an optional argument to New.
|
||||
type Option func(*Lexer) error
|
||||
|
||||
// BOMMode option selects how the lexer handles BOMs. See the BOM* constants for details.
|
||||
func BOMMode(mode int) Option {
|
||||
return func(l *Lexer) error {
|
||||
l.bomMode = mode
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorFunc option sets a function called when an, for example I/O error,
|
||||
// occurs. The default is to call Error with the position and message already
|
||||
// formated as a string.
|
||||
func ErrorFunc(f func(token.Pos, string)) Option {
|
||||
return func(l *Lexer) error {
|
||||
l.errorf = f
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// RuneClass option sets the function used to convert runes to character
|
||||
// classes.
|
||||
func RuneClass(f func(rune) int) Option {
|
||||
return func(l *Lexer) error {
|
||||
l.classf = f
|
||||
return nil
|
||||
}
|
||||
}
|
||||
40
vendor/github.com/cznic/golex/lex/doc.go
generated
vendored
Normal file
40
vendor/github.com/cznic/golex/lex/doc.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2015 The golex Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package lex is a Unicode-friendly run time library for golex[0] generated
|
||||
// lexical analyzers[1].
|
||||
//
|
||||
// Changelog
|
||||
//
|
||||
// 2015-04-08: Initial release.
|
||||
//
|
||||
// Character classes
|
||||
//
|
||||
// Golex internally handles only 8 bit "characters". Many Unicode-aware
|
||||
// tokenizers do not actually need to recognize every Unicode rune, but only
|
||||
// some particular partitions/subsets. Like, for example, a particular Unicode
|
||||
// category, say upper case letters: Lu.
|
||||
//
|
||||
// The idea is to convert all runes in a particular set as a single 8 bit
|
||||
// character allocated outside the ASCII range of codes. The token value, a
|
||||
// string of runes and their exact positions is collected as usual (see the
|
||||
// Token and TokenBytes method), but the tokenizer DFA is simpler (and thus
|
||||
// smaller and perhaps also faster) when this technique is used. In the example
|
||||
// program (see below), recognizing (and skipping) white space, integer
|
||||
// literals, one keyword and Go identifiers requires only an 8 state DFA[5].
|
||||
//
|
||||
// To provide the conversion from runes to character classes, "install" your
|
||||
// converting function using the RuneClass option.
|
||||
//
|
||||
// References
|
||||
//
|
||||
// -
|
||||
//
|
||||
// [0]: http://godoc.org/github.com/cznic/golex
|
||||
// [1]: http://en.wikipedia.org/wiki/Lexical_analysis
|
||||
// [2]: http://golang.org/cmd/yacc/
|
||||
// [3]: https://github.com/cznic/golex/blob/master/lex/example.l
|
||||
// [4]: http://golang.org/pkg/io/#RuneReader
|
||||
// [5]: https://github.com/cznic/golex/blob/master/lex/dfa
|
||||
package lex
|
||||
40
vendor/github.com/cznic/internal/file/file.go
generated
vendored
40
vendor/github.com/cznic/internal/file/file.go
generated
vendored
@@ -124,11 +124,23 @@ func (f *mem) Truncate(size int64) (err error) {
|
||||
}
|
||||
|
||||
first := size >> f.pgBits
|
||||
if size&int64(f.pgMask) != 0 {
|
||||
if po := size & int64(f.pgMask); po != 0 {
|
||||
if p := f.m[first]; p != nil {
|
||||
b := (*p)[po:]
|
||||
for i := range b {
|
||||
b[i] = 0
|
||||
}
|
||||
}
|
||||
first++
|
||||
}
|
||||
last := f.size >> f.pgBits
|
||||
if f.size&int64(f.pgMask) != 0 {
|
||||
if po := f.size & int64(f.pgMask); po != 0 {
|
||||
if p := f.m[last]; p != nil {
|
||||
b := (*p)[po:]
|
||||
for i := range b {
|
||||
b[i] = 0
|
||||
}
|
||||
}
|
||||
last++
|
||||
}
|
||||
for ; first <= last; first++ {
|
||||
@@ -143,6 +155,10 @@ func (f *mem) Truncate(size int64) (err error) {
|
||||
}
|
||||
|
||||
func (f *mem) WriteAt(b []byte, off int64) (n int, err error) {
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
pi := off >> f.pgBits
|
||||
po := int(off) & f.pgMask
|
||||
n = len(b)
|
||||
@@ -319,11 +335,23 @@ func (f *file) Truncate(size int64) (err error) {
|
||||
}
|
||||
|
||||
first := size >> f.pgBits
|
||||
if size&int64(f.pgMask) != 0 {
|
||||
if po := size & int64(f.pgMask); po != 0 {
|
||||
if p := f.m[first]; p != nil {
|
||||
b := p[po:]
|
||||
for i := range b {
|
||||
b[i] = 0
|
||||
}
|
||||
}
|
||||
first++
|
||||
}
|
||||
last := f.size >> f.pgBits
|
||||
if f.size&int64(f.pgMask) != 0 {
|
||||
if po := f.size & int64(f.pgMask); po != 0 {
|
||||
if p := f.m[last]; p != nil {
|
||||
b := p[po:]
|
||||
for i := range b {
|
||||
b[i] = 0
|
||||
}
|
||||
}
|
||||
last++
|
||||
}
|
||||
for ; first <= last; first++ {
|
||||
@@ -349,6 +377,10 @@ func (f *file) Truncate(size int64) (err error) {
|
||||
}
|
||||
|
||||
func (f *file) WriteAt(b []byte, off int64) (n int, err error) {
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
pi := off >> f.pgBits
|
||||
po := int(off) & f.pgMask
|
||||
n = len(b)
|
||||
|
||||
277
vendor/github.com/cznic/mathutil/mathutil.go
generated
vendored
277
vendor/github.com/cznic/mathutil/mathutil.go
generated
vendored
@@ -7,6 +7,13 @@
|
||||
//
|
||||
// Release history and compatibility issues
|
||||
//
|
||||
// 2017-10-14: New variadic functions for Max/Min. Ex:
|
||||
// func MaxVal(val int, vals ...int) int {
|
||||
// func MinVal(val int, vals ...int) int {
|
||||
// func MaxByteVal(val byte, vals ...byte) byte {
|
||||
// func MinByteVal(val byte, vals ...byte) byte {
|
||||
// ...
|
||||
//
|
||||
// 2016-10-10: New functions QuadPolyDiscriminant and QuadPolyFactors.
|
||||
//
|
||||
// 2013-12-13: The following functions have been REMOVED
|
||||
@@ -631,6 +638,33 @@ func Min(a, b int) int {
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxVal returns the largest argument passed.
|
||||
func MaxVal(val int, vals ...int) int {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MinVal returns the smallest argument passed.
|
||||
func MinVal(val int, vals ...int) int {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Clamp returns a value restricted between lo and hi.
|
||||
func Clamp(v, lo, hi int) int {
|
||||
return Min(Max(v, lo), hi)
|
||||
}
|
||||
|
||||
// UMax returns the larger of a and b.
|
||||
func UMax(a, b uint) uint {
|
||||
if a > b {
|
||||
@@ -649,6 +683,33 @@ func UMin(a, b uint) uint {
|
||||
return b
|
||||
}
|
||||
|
||||
// UMaxVal returns the largest argument passed.
|
||||
func UMaxVal(val uint, vals ...uint) uint {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// UMinVal returns the smallest argument passed.
|
||||
func UMinVal(val uint, vals ...uint) uint {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// UClamp returns a value restricted between lo and hi.
|
||||
func UClamp(v, lo, hi uint) uint {
|
||||
return UMin(UMax(v, lo), hi)
|
||||
}
|
||||
|
||||
// MaxByte returns the larger of a and b.
|
||||
func MaxByte(a, b byte) byte {
|
||||
if a > b {
|
||||
@@ -667,6 +728,33 @@ func MinByte(a, b byte) byte {
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxByteVal returns the largest argument passed.
|
||||
func MaxByteVal(val byte, vals ...byte) byte {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MinByteVal returns the smallest argument passed.
|
||||
func MinByteVal(val byte, vals ...byte) byte {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ClampByte returns a value restricted between lo and hi.
|
||||
func ClampByte(v, lo, hi byte) byte {
|
||||
return MinByte(MaxByte(v, lo), hi)
|
||||
}
|
||||
|
||||
// MaxInt8 returns the larger of a and b.
|
||||
func MaxInt8(a, b int8) int8 {
|
||||
if a > b {
|
||||
@@ -685,6 +773,33 @@ func MinInt8(a, b int8) int8 {
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxInt8Val returns the largest argument passed.
|
||||
func MaxInt8Val(val int8, vals ...int8) int8 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MinInt8Val returns the smallest argument passed.
|
||||
func MinInt8Val(val int8, vals ...int8) int8 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ClampInt8 returns a value restricted between lo and hi.
|
||||
func ClampInt8(v, lo, hi int8) int8 {
|
||||
return MinInt8(MaxInt8(v, lo), hi)
|
||||
}
|
||||
|
||||
// MaxUint16 returns the larger of a and b.
|
||||
func MaxUint16(a, b uint16) uint16 {
|
||||
if a > b {
|
||||
@@ -703,6 +818,33 @@ func MinUint16(a, b uint16) uint16 {
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxUint16Val returns the largest argument passed.
|
||||
func MaxUint16Val(val uint16, vals ...uint16) uint16 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MinUint16Val returns the smallest argument passed.
|
||||
func MinUint16Val(val uint16, vals ...uint16) uint16 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ClampUint16 returns a value restricted between lo and hi.
|
||||
func ClampUint16(v, lo, hi uint16) uint16 {
|
||||
return MinUint16(MaxUint16(v, lo), hi)
|
||||
}
|
||||
|
||||
// MaxInt16 returns the larger of a and b.
|
||||
func MaxInt16(a, b int16) int16 {
|
||||
if a > b {
|
||||
@@ -721,6 +863,33 @@ func MinInt16(a, b int16) int16 {
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxInt16Val returns the largest argument passed.
|
||||
func MaxInt16Val(val int16, vals ...int16) int16 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MinInt16Val returns the smallest argument passed.
|
||||
func MinInt16Val(val int16, vals ...int16) int16 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ClampInt16 returns a value restricted between lo and hi.
|
||||
func ClampInt16(v, lo, hi int16) int16 {
|
||||
return MinInt16(MaxInt16(v, lo), hi)
|
||||
}
|
||||
|
||||
// MaxUint32 returns the larger of a and b.
|
||||
func MaxUint32(a, b uint32) uint32 {
|
||||
if a > b {
|
||||
@@ -739,6 +908,33 @@ func MinUint32(a, b uint32) uint32 {
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxUint32Val returns the largest argument passed.
|
||||
func MaxUint32Val(val uint32, vals ...uint32) uint32 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MinUint32Val returns the smallest argument passed.
|
||||
func MinUint32Val(val uint32, vals ...uint32) uint32 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ClampUint32 returns a value restricted between lo and hi.
|
||||
func ClampUint32(v, lo, hi uint32) uint32 {
|
||||
return MinUint32(MaxUint32(v, lo), hi)
|
||||
}
|
||||
|
||||
// MaxInt32 returns the larger of a and b.
|
||||
func MaxInt32(a, b int32) int32 {
|
||||
if a > b {
|
||||
@@ -757,6 +953,33 @@ func MinInt32(a, b int32) int32 {
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxInt32Val returns the largest argument passed.
|
||||
func MaxInt32Val(val int32, vals ...int32) int32 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MinInt32Val returns the smallest argument passed.
|
||||
func MinInt32Val(val int32, vals ...int32) int32 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ClampInt32 returns a value restricted between lo and hi.
|
||||
func ClampInt32(v, lo, hi int32) int32 {
|
||||
return MinInt32(MaxInt32(v, lo), hi)
|
||||
}
|
||||
|
||||
// MaxUint64 returns the larger of a and b.
|
||||
func MaxUint64(a, b uint64) uint64 {
|
||||
if a > b {
|
||||
@@ -775,6 +998,33 @@ func MinUint64(a, b uint64) uint64 {
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxUint64Val returns the largest argument passed.
|
||||
func MaxUint64Val(val uint64, vals ...uint64) uint64 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MinUint64Val returns the smallest argument passed.
|
||||
func MinUint64Val(val uint64, vals ...uint64) uint64 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ClampUint64 returns a value restricted between lo and hi.
|
||||
func ClampUint64(v, lo, hi uint64) uint64 {
|
||||
return MinUint64(MaxUint64(v, lo), hi)
|
||||
}
|
||||
|
||||
// MaxInt64 returns the larger of a and b.
|
||||
func MaxInt64(a, b int64) int64 {
|
||||
if a > b {
|
||||
@@ -793,6 +1043,33 @@ func MinInt64(a, b int64) int64 {
|
||||
return b
|
||||
}
|
||||
|
||||
// MaxInt64Val returns the largest argument passed.
|
||||
func MaxInt64Val(val int64, vals ...int64) int64 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v > res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MinInt64Val returns the smallest argument passed.
|
||||
func MinInt64Val(val int64, vals ...int64) int64 {
|
||||
res := val
|
||||
for _, v := range vals {
|
||||
if v < res {
|
||||
res = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ClampInt64 returns a value restricted between lo and hi.
|
||||
func ClampInt64(v, lo, hi int64) int64 {
|
||||
return MinInt64(MaxInt64(v, lo), hi)
|
||||
}
|
||||
|
||||
// ToBase produces n in base b. For example
|
||||
//
|
||||
// ToBase(2047, 22) -> [1, 5, 4]
|
||||
|
||||
2
vendor/github.com/cznic/mathutil/mersenne/mersenne.go
generated
vendored
2
vendor/github.com/cznic/mathutil/mersenne/mersenne.go
generated
vendored
@@ -146,7 +146,7 @@ It is conjectured that every odd d ∊ N divides infinitely many Mersenne number
|
||||
The returned n should be the exponent of smallest such Mn.
|
||||
|
||||
NOTE: The computation of n from a given d performs roughly in O(n). It is
|
||||
thus highly recomended to use the 'max' argument to limit the "searched"
|
||||
thus highly recommended to use the 'max' argument to limit the "searched"
|
||||
exponent upper bound as appropriate. Otherwise the computation can take a long
|
||||
time as a large factor can be a divisor of a Mn with exponent above the uint32
|
||||
limits.
|
||||
|
||||
2
vendor/github.com/cznic/ql/btree.go
generated
vendored
2
vendor/github.com/cznic/ql/btree.go
generated
vendored
@@ -270,7 +270,6 @@ func (t *tree) extract(q *d, i int) { // (r []interface{}) {
|
||||
}
|
||||
q.d[q.c] = zde // GC
|
||||
t.c--
|
||||
return
|
||||
}
|
||||
|
||||
func (t *tree) find(q interface{}, k []interface{}) (i int, ok bool) {
|
||||
@@ -491,7 +490,6 @@ func (t *tree) Set(k []interface{}, v []interface{}) {
|
||||
|
||||
z := t.insert(&d{}, 0, k, v)
|
||||
t.r, t.first, t.last = z, z, z
|
||||
return
|
||||
}
|
||||
|
||||
func (t *tree) split(p *x, q *d, pi, i int, k []interface{}, v []interface{}) {
|
||||
|
||||
21
vendor/github.com/cznic/ql/builtin.go
generated
vendored
21
vendor/github.com/cznic/ql/builtin.go
generated
vendored
@@ -53,6 +53,7 @@ var builtin = map[string]struct {
|
||||
"second": {builtinSecond, 1, 1, true, false},
|
||||
"seconds": {builtinSeconds, 1, 1, true, false},
|
||||
"since": {builtinSince, 1, 1, false, false},
|
||||
"sleep": {builtinSleep, 1, 1, false, false},
|
||||
"sum": {builtinSum, 1, 1, false, true},
|
||||
"timeIn": {builtinTimeIn, 2, 2, true, false},
|
||||
"weekday": {builtinWeekday, 1, 1, true, false},
|
||||
@@ -873,6 +874,26 @@ func builtinSince(arg []interface{}, ctx map[interface{}]interface{}) (v interfa
|
||||
}
|
||||
}
|
||||
|
||||
func builtinSleep(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
||||
switch x := arg[0].(type) {
|
||||
case nil:
|
||||
return nil, nil
|
||||
case time.Duration:
|
||||
time.Sleep(x)
|
||||
return nil, nil
|
||||
case idealInt:
|
||||
v := time.Second * time.Duration(int64(x))
|
||||
time.Sleep(v)
|
||||
return nil, nil
|
||||
case int64:
|
||||
v := time.Second * time.Duration(x)
|
||||
time.Sleep(v)
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, invArg(x, "sleep")
|
||||
}
|
||||
}
|
||||
|
||||
func builtinSum(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
||||
if _, ok := ctx["$agg0"]; ok {
|
||||
return
|
||||
|
||||
21
vendor/github.com/cznic/ql/doc.go
generated
vendored
21
vendor/github.com/cznic/ql/doc.go
generated
vendored
@@ -213,12 +213,14 @@
|
||||
// newline = . // the Unicode code point U+000A
|
||||
// unicode_char = . // an arbitrary Unicode code point except newline
|
||||
// ascii_letter = "a" … "z" | "A" … "Z" .
|
||||
// unicode_letter = . // Unicode category L.
|
||||
// unicode_digit = . // Unocode category D.
|
||||
//
|
||||
// Letters and digits
|
||||
//
|
||||
// The underscore character _ (U+005F) is considered a letter.
|
||||
//
|
||||
// letter = ascii_letter | "_" .
|
||||
// letter = ascii_letter | unicode_letter | "_" .
|
||||
// decimal_digit = "0" … "9" .
|
||||
// octal_digit = "0" … "7" .
|
||||
// hex_digit = "0" … "9" | "A" … "F" | "a" … "f" .
|
||||
@@ -262,7 +264,7 @@
|
||||
// identifier is a sequence of one or more letters and digits. The first
|
||||
// character in an identifier must be a letter.
|
||||
//
|
||||
// identifier = letter { letter | decimal_digit } .
|
||||
// identifier = letter { letter | decimal_digit | unicode_digit } .
|
||||
//
|
||||
// For example
|
||||
//
|
||||
@@ -1089,7 +1091,7 @@
|
||||
//
|
||||
// - Rational values are comparable and ordered, in the usual way.
|
||||
//
|
||||
// - String values are comparable and ordered, lexically byte-wise.
|
||||
// - String and Blob values are comparable and ordered, lexically byte-wise.
|
||||
//
|
||||
// - Time values are comparable and ordered.
|
||||
//
|
||||
@@ -1738,7 +1740,7 @@
|
||||
// The result can be filtered using a WhereClause and orderd by the OrderBy
|
||||
// clause.
|
||||
//
|
||||
// SelectStmt = "SELECT" [ "DISTINCT" ] ( "*" | FieldList ) "FROM" RecordSetList
|
||||
// SelectStmt = "SELECT" [ "DISTINCT" ] ( "*" | FieldList ) [ "FROM" RecordSetList ]
|
||||
// [ JoinClause ] [ WhereClause ] [ GroupByClause ] [ OrderBy ] [ Limit ] [ Offset ].
|
||||
//
|
||||
// JoinClause = ( "LEFT" | "RIGHT" | "FULL" ) [ "OUTER" ] "JOIN" RecordSet "ON" Expression .
|
||||
@@ -1878,7 +1880,16 @@
|
||||
// It is an error if the expression evaluates to a non null value of non bool
|
||||
// type.
|
||||
//
|
||||
// WhereClause = "WHERE" Expression .
|
||||
// Another form of the WHERE clause is an existence predicate of a
|
||||
// parenthesized select statement. The EXISTS form evaluates to true if the
|
||||
// parenthesized SELECT statement produces a non empty record set. The NOT
|
||||
// EXISTS form evaluates to true if the parenthesized SELECT statement produces
|
||||
// an empty record set. The parenthesized SELECT statement is evaluated only
|
||||
// once (TODO issue #159).
|
||||
//
|
||||
// WhereClause = "WHERE" Expression
|
||||
// | "WHERE" "EXISTS" "(" SelectStmt ")"
|
||||
// | "WHERE" "NOT" "EXISTS" "(" SelectStmt ")" .
|
||||
//
|
||||
// Recordset grouping
|
||||
//
|
||||
|
||||
48
vendor/github.com/cznic/ql/driver.go
generated
vendored
48
vendor/github.com/cznic/ql/driver.go
generated
vendored
@@ -375,10 +375,8 @@ func driverQuery(db *driverDB, ctx *TCtx, list List, args []driver.Value) (drive
|
||||
switch n := len(rss); n {
|
||||
case 0:
|
||||
return nil, errNoResult
|
||||
case 1:
|
||||
return newdriverRows(rss[len(rss)-1]), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("query produced %d result sets, expected only one", n)
|
||||
return newDriverMultiRows(rss), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +467,7 @@ func (r *driverRows) Next(dest []driver.Value) error {
|
||||
switch v := xi.(type) {
|
||||
case nil, int64, float64, bool, []byte, time.Time:
|
||||
dest[i] = v
|
||||
case complex64, complex128, *big.Int, *big.Rat:
|
||||
case complex64, complex128, *big.Int, *big.Rat, idealComplex:
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "%v", v)
|
||||
dest[i] = buf.Bytes()
|
||||
@@ -495,6 +493,12 @@ func (r *driverRows) Next(dest []driver.Value) error {
|
||||
dest[i] = int64(v)
|
||||
case string:
|
||||
dest[i] = []byte(v)
|
||||
case idealInt:
|
||||
dest[i] = int64(v)
|
||||
case idealUint:
|
||||
dest[i] = int64(v)
|
||||
case idealFloat:
|
||||
dest[i] = float64(v)
|
||||
default:
|
||||
return fmt.Errorf("internal error 004")
|
||||
}
|
||||
@@ -508,6 +512,42 @@ func (r *driverRows) Next(dest []driver.Value) error {
|
||||
}
|
||||
}
|
||||
|
||||
type driverMultiRows struct {
|
||||
rs []Recordset
|
||||
pos int
|
||||
active *driverRows
|
||||
}
|
||||
|
||||
func newDriverMultiRows(rs []Recordset) *driverMultiRows {
|
||||
return &driverMultiRows{
|
||||
rs: rs,
|
||||
active: newdriverRows(rs[0]),
|
||||
}
|
||||
}
|
||||
func (r *driverMultiRows) Columns() []string {
|
||||
return r.active.Columns()
|
||||
}
|
||||
func (r *driverMultiRows) Close() error {
|
||||
return r.active.Close()
|
||||
}
|
||||
|
||||
func (r *driverMultiRows) HasNextResultSet() bool {
|
||||
return r.pos+1 < len(r.rs)
|
||||
}
|
||||
func (r *driverMultiRows) NextResultSet() error {
|
||||
if r.HasNextResultSet() {
|
||||
r.active.Close()
|
||||
r.pos++
|
||||
r.active = newdriverRows(r.rs[r.pos])
|
||||
return nil
|
||||
}
|
||||
return io.EOF
|
||||
}
|
||||
|
||||
func (r *driverMultiRows) Next(dest []driver.Value) error {
|
||||
return r.active.Next(dest)
|
||||
}
|
||||
|
||||
// driverStmt is a prepared statement. It is bound to a driverConn and not used
|
||||
// by multiple goroutines concurrently.
|
||||
type driverStmt struct {
|
||||
|
||||
140
vendor/github.com/cznic/ql/driver1.8.go
generated
vendored
Normal file
140
vendor/github.com/cznic/ql/driver1.8.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
// +build go1.8
|
||||
|
||||
package ql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const prefix = "$"
|
||||
|
||||
func (c *driverConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
|
||||
query, vals, err := replaceNamed(query, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.Exec(query, vals)
|
||||
}
|
||||
|
||||
func replaceNamed(query string, args []driver.NamedValue) (string, []driver.Value, error) {
|
||||
toks, err := tokenize(query)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
a := make([]driver.Value, len(args))
|
||||
m := map[string]int{}
|
||||
for _, v := range args {
|
||||
m[v.Name] = v.Ordinal
|
||||
a[v.Ordinal-1] = v.Value
|
||||
}
|
||||
for i, v := range toks {
|
||||
if len(v) > 1 && strings.HasPrefix(v, prefix) {
|
||||
if v[1] >= '1' && v[1] <= '9' {
|
||||
continue
|
||||
}
|
||||
|
||||
nm := v[1:]
|
||||
k, ok := m[nm]
|
||||
if !ok {
|
||||
return query, nil, fmt.Errorf("unknown named parameter %s", nm)
|
||||
}
|
||||
|
||||
toks[i] = fmt.Sprintf("$%d", k)
|
||||
}
|
||||
}
|
||||
return strings.Join(toks, " "), a, nil
|
||||
}
|
||||
|
||||
func (c *driverConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
|
||||
query, vals, err := replaceNamed(query, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.Query(query, vals)
|
||||
}
|
||||
|
||||
func (c *driverConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
|
||||
query, err := filterNamedArgs(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.Prepare(query)
|
||||
}
|
||||
|
||||
func filterNamedArgs(query string) (string, error) {
|
||||
toks, err := tokenize(query)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
n := 0
|
||||
for _, v := range toks {
|
||||
if len(v) > 1 && strings.HasPrefix(v, prefix) && v[1] >= '1' && v[1] <= '9' {
|
||||
m, err := strconv.ParseUint(v[1:], 10, 31)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if int(m) > n {
|
||||
n = int(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, v := range toks {
|
||||
if len(v) > 1 && strings.HasPrefix(v, prefix) {
|
||||
if v[1] >= '1' && v[1] <= '9' {
|
||||
continue
|
||||
}
|
||||
|
||||
n++
|
||||
toks[i] = fmt.Sprintf("$%d", n)
|
||||
}
|
||||
}
|
||||
return strings.Join(toks, " "), nil
|
||||
}
|
||||
|
||||
func (s *driverStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
|
||||
a := make([]driver.Value, len(args))
|
||||
for k, v := range args {
|
||||
a[k] = v.Value
|
||||
}
|
||||
return s.Exec(a)
|
||||
}
|
||||
|
||||
func (s *driverStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
|
||||
a := make([]driver.Value, len(args))
|
||||
for k, v := range args {
|
||||
a[k] = v.Value
|
||||
}
|
||||
return s.Query(a)
|
||||
}
|
||||
|
||||
func tokenize(s string) (r []string, _ error) {
|
||||
lx, err := newLexer(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var lval yySymType
|
||||
for lx.Lex(&lval) != 0 {
|
||||
s := string(lx.TokenBytes(nil))
|
||||
if s != "" {
|
||||
switch s[len(s)-1] {
|
||||
case '"':
|
||||
s = "\"" + s
|
||||
case '`':
|
||||
s = "`" + s
|
||||
}
|
||||
}
|
||||
r = append(r, s)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
43
vendor/github.com/cznic/ql/expr.go
generated
vendored
43
vendor/github.com/cznic/ql/expr.go
generated
vendored
@@ -5,6 +5,7 @@
|
||||
package ql
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"regexp"
|
||||
@@ -779,6 +780,13 @@ func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
case []byte:
|
||||
switch y := b.(type) {
|
||||
case []byte:
|
||||
return bytes.Equal(x, y), nil
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
default:
|
||||
return invOp2(a, b, op)
|
||||
}
|
||||
@@ -930,6 +938,13 @@ func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
case []byte:
|
||||
switch y := b.(type) {
|
||||
case []byte:
|
||||
return bytes.Compare(x, y) < 0, nil
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
default:
|
||||
return invOp2(a, b, op)
|
||||
}
|
||||
@@ -1081,6 +1096,13 @@ func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
case []byte:
|
||||
switch y := b.(type) {
|
||||
case []byte:
|
||||
return bytes.Compare(x, y) <= 0, nil
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
default:
|
||||
return invOp2(a, b, op)
|
||||
}
|
||||
@@ -1232,6 +1254,13 @@ func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
case []byte:
|
||||
switch y := b.(type) {
|
||||
case []byte:
|
||||
return bytes.Compare(x, y) >= 0, nil
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
default:
|
||||
return invOp2(a, b, op)
|
||||
}
|
||||
@@ -1403,6 +1432,13 @@ func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
case []byte:
|
||||
switch y := b.(type) {
|
||||
case []byte:
|
||||
return !bytes.Equal(x, y), nil
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
default:
|
||||
return invOp2(a, b, op)
|
||||
}
|
||||
@@ -1574,6 +1610,13 @@ func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
case []byte:
|
||||
switch y := b.(type) {
|
||||
case []byte:
|
||||
return bytes.Equal(x, y), nil
|
||||
default:
|
||||
return invOp2(x, y, op)
|
||||
}
|
||||
default:
|
||||
return invOp2(a, b, op)
|
||||
}
|
||||
|
||||
154
vendor/github.com/cznic/ql/lexer.go
generated
vendored
Normal file
154
vendor/github.com/cznic/ql/lexer.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright 2017 The ql Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/cznic/golex/lex"
|
||||
)
|
||||
|
||||
const (
|
||||
ccEOF = iota + 0x80
|
||||
ccLetter
|
||||
ccDigit
|
||||
ccOther
|
||||
)
|
||||
|
||||
func runeClass(r rune) int {
|
||||
switch {
|
||||
case r == lex.RuneEOF:
|
||||
return ccEOF
|
||||
case r < 0x80:
|
||||
return int(r)
|
||||
case unicode.IsLetter(r):
|
||||
return ccLetter
|
||||
case unicode.IsDigit(r):
|
||||
return ccDigit
|
||||
default:
|
||||
return ccOther
|
||||
}
|
||||
}
|
||||
|
||||
type lexer struct {
|
||||
*lex.Lexer
|
||||
agg []bool
|
||||
col int
|
||||
errs scanner.ErrorList
|
||||
expr expression
|
||||
file *token.File
|
||||
inj int
|
||||
line int
|
||||
list []stmt
|
||||
params int
|
||||
root bool
|
||||
sc int
|
||||
}
|
||||
|
||||
func newLexer(src string) (*lexer, error) {
|
||||
fset := token.NewFileSet()
|
||||
file := fset.AddFile("", -1, len(src))
|
||||
l := &lexer{
|
||||
file: file,
|
||||
}
|
||||
l0, err := lex.New(
|
||||
file,
|
||||
strings.NewReader(src),
|
||||
lex.ErrorFunc(func(pos token.Pos, msg string) {
|
||||
l.errPos(pos, msg)
|
||||
}),
|
||||
lex.RuneClass(runeClass),
|
||||
lex.BOMMode(lex.BOMIgnoreFirst),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l.Lexer = l0
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (l *lexer) errPos(pos token.Pos, format string, arg ...interface{}) {
|
||||
l.errs.Add(l.file.Position(pos), fmt.Sprintf(format, arg...))
|
||||
}
|
||||
|
||||
func (l *lexer) err(s string, arg ...interface{}) {
|
||||
l.errPos(l.Last.Pos(), s, arg...)
|
||||
}
|
||||
|
||||
// Implements yyLexer.
|
||||
func (l *lexer) Error(s string) {
|
||||
l.err(s)
|
||||
}
|
||||
|
||||
func (l *lexer) int(lval *yySymType, im bool) int {
|
||||
val := l.TokenBytes(nil)
|
||||
if im {
|
||||
val = val[:len(val)-1]
|
||||
}
|
||||
n, err := strconv.ParseUint(string(val), 0, 64)
|
||||
if err != nil {
|
||||
l.err("integer literal: %v", err)
|
||||
return int(unicode.ReplacementChar)
|
||||
}
|
||||
|
||||
if im {
|
||||
lval.item = idealComplex(complex(0, float64(n)))
|
||||
return imaginaryLit
|
||||
}
|
||||
|
||||
switch {
|
||||
case n < math.MaxInt64:
|
||||
lval.item = idealInt(n)
|
||||
default:
|
||||
lval.item = idealUint(n)
|
||||
}
|
||||
return intLit
|
||||
}
|
||||
|
||||
func (l *lexer) float(lval *yySymType, im bool) int {
|
||||
val := l.TokenBytes(nil)
|
||||
if im {
|
||||
val = val[:len(val)-1]
|
||||
}
|
||||
n, err := strconv.ParseFloat(string(val), 64)
|
||||
if err != nil {
|
||||
l.err("float literal: %v", err)
|
||||
return int(unicode.ReplacementChar)
|
||||
}
|
||||
|
||||
if im {
|
||||
lval.item = idealComplex(complex(0, n))
|
||||
return imaginaryLit
|
||||
}
|
||||
|
||||
lval.item = idealFloat(n)
|
||||
return floatLit
|
||||
}
|
||||
|
||||
func (l *lexer) str(lval *yySymType, pref string) int {
|
||||
val := l.TokenBytes(nil)
|
||||
l.sc = 0
|
||||
s := pref + string(val)
|
||||
s, err := strconv.Unquote(s)
|
||||
if err != nil {
|
||||
l.err("string literal: %v", err)
|
||||
return int(unicode.ReplacementChar)
|
||||
}
|
||||
|
||||
lval.item = s
|
||||
return stringLit
|
||||
}
|
||||
|
||||
func (l *lexer) npos() (line, col int) {
|
||||
pos := l.file.Position(l.Last.Pos())
|
||||
return pos.Line, pos.Column
|
||||
}
|
||||
11
vendor/github.com/cznic/ql/mem.go
generated
vendored
11
vendor/github.com/cznic/ql/mem.go
generated
vendored
@@ -11,6 +11,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -247,6 +248,7 @@ type mem struct {
|
||||
recycler []int
|
||||
tnl int
|
||||
rollback *undos
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func newMemStorage() (s *mem, err error) {
|
||||
@@ -278,10 +280,13 @@ func (s *mem) newUndo(tag int, h int64, data []interface{}) {
|
||||
func (s *mem) Acid() bool { return false }
|
||||
|
||||
func (s *mem) Close() (err error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.tnl != 0 {
|
||||
return fmt.Errorf("cannot close DB while open transaction exist")
|
||||
}
|
||||
*s = mem{}
|
||||
s.data, s.recycler, s.rollback = nil, nil, nil
|
||||
s.id, s.tnl = 0, 0
|
||||
return
|
||||
}
|
||||
|
||||
@@ -453,6 +458,8 @@ func (s *mem) Create(data ...interface{}) (h int64, err error) {
|
||||
}
|
||||
|
||||
func (s *mem) Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
if i := int(h); i != 0 && i < len(s.data) {
|
||||
d := s.clone(s.data[h]...)
|
||||
if cols == nil {
|
||||
@@ -822,7 +829,6 @@ func (t *xtree) extract(q *xd, i int) { // (r int64) {
|
||||
}
|
||||
q.xd[q.c] = zxde // GC
|
||||
t.c--
|
||||
return
|
||||
}
|
||||
|
||||
func (t *xtree) find(q interface{}, k indexKey) (i int, ok bool) {
|
||||
@@ -1043,7 +1049,6 @@ func (t *xtree) Set(k indexKey, v int) {
|
||||
|
||||
z := t.insert(&xd{}, 0, k, v)
|
||||
t.r, t.first, t.last = z, z, z
|
||||
return
|
||||
}
|
||||
|
||||
func (t *xtree) split(p *xx, q *xd, pi, i int, k indexKey, v int) {
|
||||
|
||||
2059
vendor/github.com/cznic/ql/parser.go
generated
vendored
2059
vendor/github.com/cznic/ql/parser.go
generated
vendored
File diff suppressed because it is too large
Load Diff
35
vendor/github.com/cznic/ql/plan.go
generated
vendored
35
vendor/github.com/cznic/ql/plan.go
generated
vendored
@@ -49,6 +49,7 @@ var (
|
||||
_ plan = (*selectFieldsDefaultPlan)(nil)
|
||||
_ plan = (*selectFieldsGroupPlan)(nil)
|
||||
_ plan = (*selectIndexDefaultPlan)(nil)
|
||||
_ plan = (*selectDummyPlan)(nil)
|
||||
_ plan = (*sysColumnDefaultPlan)(nil)
|
||||
_ plan = (*sysIndexDefaultPlan)(nil)
|
||||
_ plan = (*sysTableDefaultPlan)(nil)
|
||||
@@ -1379,9 +1380,7 @@ func (r *explainDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []inte
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *explainDefaultPlan) explain(w strutil.Formatter) {
|
||||
return
|
||||
}
|
||||
func (r *explainDefaultPlan) explain(w strutil.Formatter) {}
|
||||
|
||||
func (r *explainDefaultPlan) fieldNames() []string {
|
||||
return []string{""}
|
||||
@@ -2798,3 +2797,33 @@ func (r *fullJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []int
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type selectDummyPlan struct {
|
||||
flds []*fld
|
||||
}
|
||||
|
||||
func (r *selectDummyPlan) hasID() bool { return true }
|
||||
|
||||
func (r *selectDummyPlan) explain(w strutil.Formatter) {
|
||||
w.Format("┌Selects values from dummy table\n└Output field names %v\n", qnames(r.fieldNames()))
|
||||
}
|
||||
|
||||
func (r *selectDummyPlan) fieldNames() []string { return make([]string, len(r.flds)) }
|
||||
|
||||
func (r *selectDummyPlan) filter(expr expression) (plan, []string, error) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
func (r *selectDummyPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
|
||||
m := map[interface{}]interface{}{}
|
||||
data := []interface{}{}
|
||||
for _, v := range r.flds {
|
||||
rst, err := v.expr.eval(ctx, m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data = append(data, rst)
|
||||
}
|
||||
_, err = f(nil, data)
|
||||
return
|
||||
}
|
||||
|
||||
124
vendor/github.com/cznic/ql/ql.go
generated
vendored
124
vendor/github.com/cznic/ql/ql.go
generated
vendored
@@ -330,8 +330,21 @@ func (r *orderByRset) plan(ctx *execCtx) (plan, error) {
|
||||
}
|
||||
|
||||
type whereRset struct {
|
||||
expr expression
|
||||
src plan
|
||||
expr expression
|
||||
src plan
|
||||
sel *selectStmt
|
||||
exists bool
|
||||
}
|
||||
|
||||
func (r *whereRset) String() string {
|
||||
if r.sel != nil {
|
||||
s := ""
|
||||
if !r.exists {
|
||||
s += " NOT "
|
||||
}
|
||||
return fmt.Sprintf("%s EXISTS ( %s )", s, strings.TrimSuffix(r.sel.String(), ";"))
|
||||
}
|
||||
return r.expr.String()
|
||||
}
|
||||
|
||||
func (r *whereRset) planBinOp(x *binaryOperation) (plan, error) {
|
||||
@@ -514,6 +527,44 @@ func (r *whereRset) planUnaryOp(x *unaryOperation) (plan, error) {
|
||||
}
|
||||
|
||||
func (r *whereRset) plan(ctx *execCtx) (plan, error) {
|
||||
o := r.src
|
||||
if r.sel != nil {
|
||||
var exists bool
|
||||
ctx.mu.RLock()
|
||||
m, ok := ctx.cache[r.sel]
|
||||
ctx.mu.RUnlock()
|
||||
if ok {
|
||||
exists = m.(bool)
|
||||
} else {
|
||||
p, err := r.sel.plan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = p.do(ctx, func(i interface{}, data []interface{}) (bool, error) {
|
||||
if len(data) > 0 {
|
||||
exists = true
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx.mu.Lock()
|
||||
ctx.cache[r.sel] = true
|
||||
ctx.mu.Unlock()
|
||||
}
|
||||
if r.exists == exists {
|
||||
return o, nil
|
||||
}
|
||||
return &nullPlan{fields: o.fieldNames()}, nil
|
||||
}
|
||||
return r.planExpr(ctx)
|
||||
}
|
||||
|
||||
func (r *whereRset) planExpr(ctx *execCtx) (plan, error) {
|
||||
if r.expr == nil {
|
||||
return &nullPlan{}, nil
|
||||
}
|
||||
expr, err := r.expr.clone(ctx.arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -567,6 +618,10 @@ type selectRset struct {
|
||||
}
|
||||
|
||||
func (r *selectRset) plan(ctx *execCtx) (plan, error) {
|
||||
if r.src == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var flds2 []*fld
|
||||
if len(r.flds) != 0 {
|
||||
m := map[string]struct{}{}
|
||||
@@ -703,8 +758,7 @@ func findCol(cols []*col, name string) (c *col) {
|
||||
}
|
||||
|
||||
func (f *col) clone() *col {
|
||||
var r col
|
||||
r = *f
|
||||
r := *f
|
||||
r.constraint = f.constraint.clone()
|
||||
if f.dflt != nil {
|
||||
r.dflt, _ = r.dflt.clone(nil)
|
||||
@@ -795,7 +849,7 @@ func newDB(store storage) (db *DB, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := &execCtx{db: db0}
|
||||
ctx := newExecCtx(db0, nil)
|
||||
for _, t := range db0.root.tables {
|
||||
if err := t.constraintsAndDefaults(ctx); err != nil {
|
||||
return nil, err
|
||||
@@ -893,7 +947,7 @@ func newDB(store storage) (db *DB, err error) {
|
||||
|
||||
func (db *DB) deleteIndex2ByIndexName(nm string) error {
|
||||
for _, s := range deleteIndex2ByIndexName.l {
|
||||
if _, err := s.exec(&execCtx{db: db, arg: []interface{}{nm}}); err != nil {
|
||||
if _, err := s.exec(newExecCtx(db, []interface{}{nm})); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -902,7 +956,7 @@ func (db *DB) deleteIndex2ByIndexName(nm string) error {
|
||||
|
||||
func (db *DB) deleteIndex2ByTableName(nm string) error {
|
||||
for _, s := range deleteIndex2ByTableName.l {
|
||||
if _, err := s.exec(&execCtx{db: db, arg: []interface{}{nm}}); err != nil {
|
||||
if _, err := s.exec(newExecCtx(db, []interface{}{nm})); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -931,7 +985,7 @@ func (db *DB) createIndex2() error {
|
||||
|
||||
expr := "id()"
|
||||
if i != 0 {
|
||||
expr = t.cols[i-1].name
|
||||
expr = t.cols0[i-1].name
|
||||
}
|
||||
|
||||
if err := db.insertIndex2(t.name, index.name, []string{expr}, index.unique, true, index.xroot); err != nil {
|
||||
@@ -1036,29 +1090,41 @@ func (db *DB) run(ctx *TCtx, ql string, arg ...interface{}) (rs []Recordset, ind
|
||||
//
|
||||
// Compile is safe for concurrent use by multiple goroutines.
|
||||
func Compile(src string) (List, error) {
|
||||
l := newLexer(src)
|
||||
l, err := newLexer(src)
|
||||
if err != nil {
|
||||
return List{}, err
|
||||
}
|
||||
|
||||
if yyParse(l) != 0 {
|
||||
return List{}, l.errs[0]
|
||||
return List{}, l.errs
|
||||
}
|
||||
|
||||
return List{l.list, l.params}, nil
|
||||
}
|
||||
|
||||
func compileExpr(src string) (expression, error) {
|
||||
l := newLexer(src)
|
||||
l, err := newLexer(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l.inj = parseExpression
|
||||
if yyParse(l) != 0 {
|
||||
return nil, l.errs[0]
|
||||
return nil, l.errs
|
||||
}
|
||||
|
||||
return l.expr, nil
|
||||
}
|
||||
|
||||
func compile(src string) (List, error) {
|
||||
l := newLexer(src)
|
||||
l, err := newLexer(src)
|
||||
if err != nil {
|
||||
return List{}, err
|
||||
}
|
||||
|
||||
l.root = true
|
||||
if yyParse(l) != 0 {
|
||||
return List{}, l.errs[0]
|
||||
return List{}, l.errs
|
||||
}
|
||||
|
||||
return List{l.list, l.params}, nil
|
||||
@@ -1263,7 +1329,7 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
|
||||
db.rwmu.RLock() // can safely grab before Unlock
|
||||
db.muUnlock()
|
||||
defer db.rwmu.RUnlock()
|
||||
rs, err = s.exec(&execCtx{db, arg}) // R/O tctx
|
||||
rs, err = s.exec(newExecCtx(db, arg)) // R/O tctx
|
||||
return rs, tnla, tnlb, err
|
||||
}
|
||||
default: // case true:
|
||||
@@ -1345,7 +1411,7 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
|
||||
db.muUnlock() // must Unlock before RLock
|
||||
db.rwmu.RLock()
|
||||
defer db.rwmu.RUnlock()
|
||||
rs, err = s.exec(&execCtx{db, arg})
|
||||
rs, err = s.exec(newExecCtx(db, arg))
|
||||
return rs, tnla, tnlb, err
|
||||
}
|
||||
|
||||
@@ -1355,7 +1421,7 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
|
||||
return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
|
||||
}
|
||||
|
||||
rs, err = s.exec(&execCtx{db, arg})
|
||||
rs, err = s.exec(newExecCtx(db, arg))
|
||||
return rs, tnla, tnlb, err
|
||||
}
|
||||
}
|
||||
@@ -1523,13 +1589,13 @@ func (db *DB) info() (r *DbInfo, err error) {
|
||||
ti := TableInfo{Name: nm}
|
||||
m := map[string]*ColumnInfo{}
|
||||
if hasColumn2 {
|
||||
rs, err := selectColumn2.l[0].exec(&execCtx{db: db, arg: []interface{}{nm}})
|
||||
rs, err := selectColumn2.l[0].exec(newExecCtx(db, []interface{}{nm}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := rs.(recordset).do(
|
||||
&execCtx{db: db, arg: []interface{}{nm}},
|
||||
newExecCtx(db, []interface{}{nm}),
|
||||
func(id interface{}, data []interface{}) (bool, error) {
|
||||
ci := &ColumnInfo{NotNull: data[1].(bool), Constraint: data[2].(string), Default: data[3].(string)}
|
||||
m[data[0].(string)] = ci
|
||||
@@ -1609,7 +1675,15 @@ type joinRset struct {
|
||||
on expression
|
||||
}
|
||||
|
||||
func (r *joinRset) isZero() bool {
|
||||
return len(r.sources) == 0 && r.typ == 0 && r.on == nil
|
||||
|
||||
}
|
||||
|
||||
func (r *joinRset) String() string {
|
||||
if r.isZero() {
|
||||
return ""
|
||||
}
|
||||
a := make([]string, len(r.sources))
|
||||
for i, pair0 := range r.sources {
|
||||
pair := pair0.([]interface{})
|
||||
@@ -1652,6 +1726,9 @@ func (r *joinRset) String() string {
|
||||
}
|
||||
|
||||
func (r *joinRset) plan(ctx *execCtx) (plan, error) {
|
||||
if r.isZero() {
|
||||
return nil, nil
|
||||
}
|
||||
rsets := make([]plan, len(r.sources))
|
||||
names := make([]string, len(r.sources))
|
||||
var err error
|
||||
@@ -1699,19 +1776,18 @@ func (r *joinRset) plan(ctx *execCtx) (plan, error) {
|
||||
if f != "" && nm != "" {
|
||||
f = fmt.Sprintf("%s.%s", nm, f)
|
||||
}
|
||||
if nm == "" {
|
||||
f = ""
|
||||
}
|
||||
fields = append(fields, f)
|
||||
}
|
||||
}
|
||||
rsets[i] = q
|
||||
}
|
||||
|
||||
if len(rsets) == 1 {
|
||||
switch len(rsets) {
|
||||
case 0:
|
||||
return nil, nil
|
||||
case 1:
|
||||
return rsets[0], nil
|
||||
}
|
||||
|
||||
right := len(rsets[len(rsets)-1].fieldNames())
|
||||
switch r.typ {
|
||||
case crossJoin:
|
||||
|
||||
194
vendor/github.com/cznic/ql/ql/main.go
generated
vendored
194
vendor/github.com/cznic/ql/ql/main.go
generated
vendored
@@ -58,6 +58,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -84,22 +85,66 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func do() (err error) {
|
||||
oDB := flag.String("db", "ql.db", "The DB file to open. It'll be created if missing.")
|
||||
oFlds := flag.Bool("fld", false, "Show recordset's field names.")
|
||||
oSchema := flag.String("schema", "", "If non empty, show the CREATE statements of matching tables and exit.")
|
||||
oTables := flag.String("tables", "", "If non empty, list matching table names and exit.")
|
||||
oTime := flag.Bool("t", false, "Measure and report time to execute the statement(s) including DB create/open/close.")
|
||||
type config struct {
|
||||
db string
|
||||
flds bool
|
||||
schema string
|
||||
tables string
|
||||
time bool
|
||||
help bool
|
||||
interactive bool
|
||||
}
|
||||
|
||||
func (c *config) parse() {
|
||||
db := flag.String("db", "ql.db", "The DB file to open. It'll be created if missing.")
|
||||
flds := flag.Bool("fld", false, "Show recordset's field names.")
|
||||
schema := flag.String("schema", "", "If non empty, show the CREATE statements of matching tables and exit.")
|
||||
tables := flag.String("tables", "", "If non empty, list matching table names and exit.")
|
||||
time := flag.Bool("t", false, "Measure and report time to execute the statement(s) including DB create/open/close.")
|
||||
help := flag.Bool("h", false, "Shows this help text.")
|
||||
interactive := flag.Bool("i", false, "runs in interactive mode")
|
||||
flag.Parse()
|
||||
c.flds = *flds
|
||||
c.db = *db
|
||||
c.schema = *schema
|
||||
c.tables = *tables
|
||||
c.time = *time
|
||||
c.help = *help
|
||||
c.interactive = *interactive
|
||||
}
|
||||
|
||||
t0 := time.Now()
|
||||
if *oTime {
|
||||
defer func() {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", time.Since(t0))
|
||||
}()
|
||||
func do() (err error) {
|
||||
cfg := &config{}
|
||||
cfg.parse()
|
||||
if cfg.help {
|
||||
flag.PrintDefaults()
|
||||
return nil
|
||||
}
|
||||
if flag.NArg() == 0 && !cfg.interactive {
|
||||
|
||||
db, err := ql.OpenFile(*oDB, &ql.Options{CanCreate: true})
|
||||
// Somehow we expect input to the ql tool.
|
||||
// This will block trying to read input from stdin
|
||||
b, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil || len(b) == 0 {
|
||||
flag.PrintDefaults()
|
||||
return nil
|
||||
}
|
||||
db, err := ql.OpenFile(cfg.db, &ql.Options{CanCreate: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
ec := db.Close()
|
||||
switch {
|
||||
case ec != nil && err != nil:
|
||||
log.Println(ec)
|
||||
case ec != nil:
|
||||
err = ec
|
||||
}
|
||||
}()
|
||||
return run(cfg, bufio.NewWriter(os.Stdout), string(b), db)
|
||||
}
|
||||
db, err := ql.OpenFile(cfg.db, &ql.Options{CanCreate: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -113,8 +158,85 @@ func do() (err error) {
|
||||
err = ec
|
||||
}
|
||||
}()
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
o := bufio.NewWriter(os.Stdout)
|
||||
if cfg.interactive {
|
||||
for {
|
||||
o.WriteString("ql> ")
|
||||
o.Flush()
|
||||
src, err := readSrc(cfg.interactive, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = run(cfg, o, src, db)
|
||||
if err != nil {
|
||||
fmt.Fprintln(o, err)
|
||||
o.Flush()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
src, err := readSrc(cfg.interactive, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return run(cfg, o, src, db)
|
||||
}
|
||||
|
||||
if pat := *oSchema; pat != "" {
|
||||
func readSrc(i bool, in *bufio.Reader) (string, error) {
|
||||
if i {
|
||||
return in.ReadString('\n')
|
||||
}
|
||||
var src string
|
||||
switch n := flag.NArg(); n {
|
||||
case 0:
|
||||
b, err := ioutil.ReadAll(in)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
src = string(b)
|
||||
default:
|
||||
a := make([]string, n)
|
||||
for i := range a {
|
||||
a[i] = flag.Arg(i)
|
||||
}
|
||||
src = strings.Join(a, " ")
|
||||
}
|
||||
return src, nil
|
||||
}
|
||||
|
||||
func run(cfg *config, o *bufio.Writer, src string, db *ql.DB) (err error) {
|
||||
defer o.Flush()
|
||||
if cfg.interactive {
|
||||
src = strings.TrimSpace(src)
|
||||
if strings.HasPrefix(src, "\\") ||
|
||||
strings.HasPrefix(src, ".") {
|
||||
switch src {
|
||||
case "\\clear", ".clear":
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "linux":
|
||||
fmt.Fprintln(o, "\033[H\033[2J")
|
||||
default:
|
||||
fmt.Fprintln(o, "clear not supported in this system")
|
||||
}
|
||||
return nil
|
||||
case "\\q", "\\exit", ".q", ".exit":
|
||||
// we make sure to close the database before exiting
|
||||
db.Close()
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
t0 := time.Now()
|
||||
if cfg.time {
|
||||
defer func() {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", time.Since(t0))
|
||||
}()
|
||||
}
|
||||
if pat := cfg.schema; pat != "" {
|
||||
re, err := regexp.Compile(pat)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -139,12 +261,12 @@ func do() (err error) {
|
||||
}
|
||||
sort.Strings(r)
|
||||
if len(r) != 0 {
|
||||
fmt.Println(strings.Join(r, "\n"))
|
||||
fmt.Fprintln(o, strings.Join(r, "\n"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if pat := *oTables; pat != "" {
|
||||
if pat := cfg.tables; pat != "" {
|
||||
re, err := regexp.Compile(pat)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -165,29 +287,18 @@ func do() (err error) {
|
||||
}
|
||||
sort.Strings(r)
|
||||
if len(r) != 0 {
|
||||
fmt.Println(strings.Join(r, "\n"))
|
||||
fmt.Fprintln(o, strings.Join(r, "\n"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var src string
|
||||
switch n := flag.NArg(); n {
|
||||
case 0:
|
||||
b, err := ioutil.ReadAll(bufio.NewReader(os.Stdin))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
src = strings.TrimSpace(src)
|
||||
|
||||
src = string(b)
|
||||
default:
|
||||
a := make([]string, n)
|
||||
for i := range a {
|
||||
a[i] = flag.Arg(i)
|
||||
}
|
||||
src = strings.Join(a, " ")
|
||||
commit := "COMMIT;"
|
||||
if !strings.HasSuffix(src, ";") {
|
||||
commit = "; " + commit
|
||||
}
|
||||
|
||||
src = "BEGIN TRANSACTION; " + src + "; COMMIT;"
|
||||
src = "BEGIN TRANSACTION; " + src + commit
|
||||
l, err := ql.Compile(src)
|
||||
if err != nil {
|
||||
log.Println(src)
|
||||
@@ -206,14 +317,21 @@ func do() (err error) {
|
||||
|
||||
switch {
|
||||
case l.IsExplainStmt():
|
||||
return rs[len(rs)-1].Do(*oFlds, func(data []interface{}) (bool, error) {
|
||||
fmt.Println(data[0])
|
||||
return rs[len(rs)-1].Do(cfg.flds, func(data []interface{}) (bool, error) {
|
||||
fmt.Fprintln(o, data[0])
|
||||
return true, nil
|
||||
})
|
||||
default:
|
||||
return rs[len(rs)-1].Do(*oFlds, func(data []interface{}) (bool, error) {
|
||||
fmt.Println(str(data))
|
||||
return true, nil
|
||||
})
|
||||
for _, rst := range rs {
|
||||
err = rst.Do(cfg.flds, func(data []interface{}) (bool, error) {
|
||||
fmt.Fprintln(o, str(data))
|
||||
return true, nil
|
||||
})
|
||||
o.Flush()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
4862
vendor/github.com/cznic/ql/scanner.go
generated
vendored
4862
vendor/github.com/cznic/ql/scanner.go
generated
vendored
File diff suppressed because it is too large
Load Diff
53
vendor/github.com/cznic/ql/stmt.go
generated
vendored
53
vendor/github.com/cznic/ql/stmt.go
generated
vendored
@@ -9,6 +9,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"sync"
|
||||
|
||||
"github.com/cznic/strutil"
|
||||
)
|
||||
|
||||
@@ -121,8 +123,18 @@ type stmt interface {
|
||||
}
|
||||
|
||||
type execCtx struct { //LATER +shared temp
|
||||
db *DB
|
||||
arg []interface{}
|
||||
db *DB
|
||||
arg []interface{}
|
||||
cache map[interface{}]interface{}
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func newExecCtx(db *DB, arg []interface{}) *execCtx {
|
||||
return &execCtx{
|
||||
db: db,
|
||||
arg: arg,
|
||||
cache: make(map[interface{}]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
type explainStmt struct {
|
||||
@@ -571,7 +583,7 @@ func (s *alterTableDropColumnStmt) exec(ctx *execCtx) (Recordset, error) {
|
||||
}
|
||||
|
||||
if _, ok := ctx.db.root.tables["__Column2"]; ok {
|
||||
if _, err := deleteColumn2.l[0].exec(&execCtx{db: ctx.db, arg: []interface{}{s.tableName, c.name}}); err != nil {
|
||||
if _, err := deleteColumn2.l[0].exec(newExecCtx(ctx.db, []interface{}{s.tableName, c.name})); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -680,7 +692,7 @@ func (s *alterTableAddStmt) exec(ctx *execCtx) (Recordset, error) {
|
||||
|
||||
if c.constraint != nil || c.dflt != nil {
|
||||
for _, s := range createColumn2.l {
|
||||
_, err := s.exec(&execCtx{db: ctx.db})
|
||||
_, err := s.exec(newExecCtx(ctx.db, nil))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -693,7 +705,7 @@ func (s *alterTableAddStmt) exec(ctx *execCtx) (Recordset, error) {
|
||||
if e := c.dflt; e != nil {
|
||||
d = e.String()
|
||||
}
|
||||
if _, err := insertColumn2.l[0].exec(&execCtx{db: ctx.db, arg: []interface{}{s.tableName, c.name, notNull, co, d}}); err != nil {
|
||||
if _, err := insertColumn2.l[0].exec(newExecCtx(ctx.db, []interface{}{s.tableName, c.name, notNull, co, d})); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -750,11 +762,16 @@ func (s *selectStmt) String() string {
|
||||
}
|
||||
b.WriteString(" " + strings.Join(a, ", "))
|
||||
}
|
||||
b.WriteString(" FROM ")
|
||||
b.WriteString(s.from.String())
|
||||
if s.from != nil {
|
||||
if !s.from.isZero() {
|
||||
b.WriteString(" FROM ")
|
||||
b.WriteString(s.from.String())
|
||||
}
|
||||
}
|
||||
|
||||
if s.where != nil {
|
||||
b.WriteString(" WHERE ")
|
||||
b.WriteString(s.where.expr.String())
|
||||
b.WriteString(s.where.String())
|
||||
}
|
||||
if s.group != nil {
|
||||
b.WriteString(" GROUP BY ")
|
||||
@@ -777,13 +794,19 @@ func (s *selectStmt) String() string {
|
||||
}
|
||||
|
||||
func (s *selectStmt) plan(ctx *execCtx) (plan, error) { //LATER overlapping goroutines/pipelines
|
||||
r, err := s.from.plan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var r plan
|
||||
var err error
|
||||
if s.from != nil {
|
||||
r, err = s.from.plan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if r == nil {
|
||||
return &selectDummyPlan{flds: s.flds}, nil
|
||||
}
|
||||
|
||||
if w := s.where; w != nil {
|
||||
if r, err = (&whereRset{expr: w.expr, src: r}).plan(ctx); err != nil {
|
||||
if r, err = (&whereRset{expr: w.expr, src: r, sel: w.sel, exists: w.exists}).plan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -1234,7 +1257,7 @@ func (s *createTableStmt) exec(ctx *execCtx) (_ Recordset, err error) {
|
||||
if c.constraint != nil || c.dflt != nil {
|
||||
if mustCreateColumn2 {
|
||||
for _, stmt := range createColumn2.l {
|
||||
_, err := stmt.exec(&execCtx{db: ctx.db})
|
||||
_, err := stmt.exec(newExecCtx(ctx.db, nil))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1250,7 +1273,7 @@ func (s *createTableStmt) exec(ctx *execCtx) (_ Recordset, err error) {
|
||||
if e := c.dflt; e != nil {
|
||||
d = e.String()
|
||||
}
|
||||
if _, err := insertColumn2.l[0].exec(&execCtx{db: ctx.db, arg: []interface{}{s.tableName, c.name, notNull, co, d}}); err != nil {
|
||||
if _, err := insertColumn2.l[0].exec(newExecCtx(ctx.db, []interface{}{s.tableName, c.name, notNull, co, d})); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
12
vendor/github.com/cznic/ql/storage.go
generated
vendored
12
vendor/github.com/cznic/ql/storage.go
generated
vendored
@@ -153,7 +153,7 @@ func (t *table) constraintsAndDefaults(ctx *execCtx) error {
|
||||
constraints := make([]*constraint, len(cols))
|
||||
defaults := make([]expression, len(cols))
|
||||
arg := []interface{}{t.name}
|
||||
rs, err := selectColumn2.l[0].exec(&execCtx{db: ctx.db, arg: arg})
|
||||
rs, err := selectColumn2.l[0].exec(newExecCtx(ctx.db, arg))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func (t *table) constraintsAndDefaults(ctx *execCtx) error {
|
||||
var rows [][]interface{}
|
||||
ok = false
|
||||
if err := rs.(recordset).do(
|
||||
&execCtx{db: ctx.db, arg: arg},
|
||||
newExecCtx(ctx.db, arg),
|
||||
func(id interface{}, data []interface{}) (more bool, err error) {
|
||||
rows = append(rows, data)
|
||||
return true, nil
|
||||
@@ -330,7 +330,7 @@ func (t *table) findIndexByColName(name string) (*col, *indexedCol) {
|
||||
continue
|
||||
}
|
||||
|
||||
if c := t.cols[i-1]; c.name == name {
|
||||
if c := t.cols0[i-1]; c.name == name {
|
||||
return c, v
|
||||
}
|
||||
}
|
||||
@@ -784,7 +784,11 @@ func (t *table) row(ctx *execCtx, h int64) (int64, []interface{}, error) {
|
||||
return -1, nil, err
|
||||
}
|
||||
|
||||
return rec[1].(int64), rec[2:], nil
|
||||
id := rec[1].(int64)
|
||||
for i, c := range t.cols {
|
||||
rec[i] = rec[c.index+2]
|
||||
}
|
||||
return id, rec[:len(t.cols)], nil
|
||||
}
|
||||
|
||||
// storage fields
|
||||
|
||||
15
vendor/github.com/cznic/strutil/strutil.go
generated
vendored
15
vendor/github.com/cznic/strutil/strutil.go
generated
vendored
@@ -397,7 +397,7 @@ func (d *GoDict) S(id int) (s string, ok bool) {
|
||||
// to a string slice over an unreferenced biger underlying string keeps the biger one
|
||||
// in memory anyway - it can't be GCed.
|
||||
func StrPack(s string) string {
|
||||
return string([]byte(s))
|
||||
return string([]byte(s)) // T(U(T)) intentional.
|
||||
}
|
||||
|
||||
// JoinFields returns strings in flds joined by sep. Flds may contain arbitrary
|
||||
@@ -665,6 +665,19 @@ func Gopath() string {
|
||||
}
|
||||
}
|
||||
|
||||
// Homepath returns the user's home directory path.
|
||||
func Homepath() string {
|
||||
// go1.8: https://github.com/golang/go/blob/74628a8b9f102bddd5078ee426efe0fd57033115/doc/code.html#L122
|
||||
switch runtime.GOOS {
|
||||
case "plan9":
|
||||
return os.Getenv("home")
|
||||
case "windows":
|
||||
return os.Getenv("USERPROFILE")
|
||||
default:
|
||||
return os.Getenv("HOME")
|
||||
}
|
||||
}
|
||||
|
||||
// ImportPath returns the import path of the caller or an error, if any.
|
||||
func ImportPath() (string, error) {
|
||||
_, file, _, ok := runtime.Caller(1)
|
||||
|
||||
Reference in New Issue
Block a user