├── testdata └── Chinook_Sqlite.sqlite ├── sqlitedb ├── errors.go ├── table_editor.go ├── partitions.go ├── table_insert.go ├── row.go ├── database_provider.go ├── utils.go ├── table.go └── database.go ├── README.md ├── main.go ├── go.mod ├── sqlitedb_test └── sqlitedb_test.go └── go.sum /testdata/Chinook_Sqlite.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mergestat/go-mysql-sqlite-server/HEAD/testdata/Chinook_Sqlite.sqlite -------------------------------------------------------------------------------- /sqlitedb/errors.go: -------------------------------------------------------------------------------- 1 | package sqlitedb 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrNoSQLiteConn = errors.New("could not retrieve SQLite connection") 7 | ErrNoInsertsAllowed = errors.New("table does not permit INSERTs") 8 | ErrNoCreateTableAllowed = errors.New("database does not permit creating tables") 9 | ErrCouldNotFindDatabase = errors.New("could not find database") 10 | ) 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## go-mysql-sqlite-server 2 | 3 | This is an *experimental* implementation of a SQLite backend for [`go-mysql-server`](https://github.com/dolthub/go-mysql-server) from DoltHub. 4 | The `go-mysql-server` is a "frontend" SQL engine based on a MySQL syntax and wire protocol implementation. 5 | It allows for pluggable "backends" as database and table providers. 6 | 7 | This project implements a SQLite backend so that a SQLite database file on disk may be exposed over a MySQL server interface. 8 | 9 | ``` 10 | go run main.go 11 | ``` 12 | -------------------------------------------------------------------------------- /sqlitedb/table_editor.go: -------------------------------------------------------------------------------- 1 | package sqlitedb 2 | 3 | import "github.com/dolthub/go-mysql-server/sql" 4 | 5 | type tableEditor struct{} 6 | 7 | func newTableEditor() *tableEditor { 8 | return &tableEditor{} 9 | } 10 | 11 | func (edit *tableEditor) StatementBegin(ctx *sql.Context) { 12 | // TODO(patrickdevivo) 13 | } 14 | 15 | func (edit *tableEditor) DiscardChanges(ctx *sql.Context, errorEncountered error) error { 16 | // TODO(patrickdevivo) 17 | return nil 18 | } 19 | 20 | func (edit *tableEditor) StatementComplete(ctx *sql.Context) error { 21 | // TODO(patrickdevivo) 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /sqlitedb/partitions.go: -------------------------------------------------------------------------------- 1 | package sqlitedb 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/dolthub/go-mysql-server/sql" 7 | ) 8 | 9 | type singlePartitionIter struct { 10 | called bool 11 | } 12 | 13 | func (iter *singlePartitionIter) Next() (sql.Partition, error) { 14 | if iter.called { 15 | return nil, io.EOF 16 | } else { 17 | iter.called = true 18 | return &partition{}, nil 19 | } 20 | } 21 | 22 | func (iter *singlePartitionIter) Close(ctx *sql.Context) error { return nil } 23 | 24 | type partition struct{} 25 | 26 | func (p *partition) Key() []byte { return []byte("single-partition-key") } 27 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crawshaw.io/sqlite/sqlitex" 5 | sqle "github.com/dolthub/go-mysql-server" 6 | "github.com/dolthub/go-mysql-server/auth" 7 | "github.com/dolthub/go-mysql-server/server" 8 | "github.com/dolthub/go-mysql-server/sql" 9 | "github.com/dolthub/go-mysql-server/sql/information_schema" 10 | "github.com/mergestat/go-mysql-sqlite-server/sqlitedb" 11 | ) 12 | 13 | const ( 14 | dbName = "testdata/Chinook_Sqlite.sqlite" 15 | ) 16 | 17 | func main() { 18 | pool, err := sqlitex.Open(dbName, 0, 10) 19 | if err != nil { 20 | panic(err) 21 | } 22 | defer func() { 23 | if err := pool.Close(); err != nil { 24 | panic(err) 25 | } 26 | }() 27 | 28 | db := sqlitedb.NewDatabase(dbName, pool, nil) 29 | engine := sqle.NewDefault( 30 | sql.NewDatabaseProvider( 31 | db, 32 | information_schema.NewInformationSchemaDatabase(), 33 | )) 34 | 35 | config := server.Config{ 36 | Protocol: "tcp", 37 | Address: "localhost:3306", 38 | Auth: auth.NewNativeSingle("root", "", auth.AllPermissions), 39 | } 40 | 41 | s, err := server.NewDefaultServer(config, engine) 42 | if err != nil { 43 | panic(err) 44 | } 45 | 46 | s.Start() 47 | } 48 | -------------------------------------------------------------------------------- /sqlitedb/table_insert.go: -------------------------------------------------------------------------------- 1 | package sqlitedb 2 | 3 | import ( 4 | "fmt" 5 | 6 | "crawshaw.io/sqlite/sqlitex" 7 | sq "github.com/Masterminds/squirrel" 8 | "github.com/dolthub/go-mysql-server/sql" 9 | ) 10 | 11 | var _ sql.InsertableTable = (*Table)(nil) 12 | var _ sql.RowInserter = (*rowInserter)(nil) 13 | 14 | type rowInserter struct { 15 | *tableEditor 16 | table *Table 17 | } 18 | 19 | func newRowInserter(table *Table) *rowInserter { 20 | return &rowInserter{ 21 | tableEditor: newTableEditor(), 22 | table: table, 23 | } 24 | } 25 | 26 | func (t *Table) Inserter(*sql.Context) sql.RowInserter { 27 | return newRowInserter(t) 28 | } 29 | 30 | func (inserter *rowInserter) Insert(ctx *sql.Context, row sql.Row) error { 31 | if inserter.table.db.options.PreventInserts { 32 | return ErrNoInsertsAllowed 33 | } 34 | conn := inserter.table.db.pool.Get(ctx) 35 | if conn == nil { 36 | return ErrNoSQLiteConn 37 | } 38 | defer inserter.table.db.pool.Put(conn) 39 | 40 | schema := inserter.table.Schema() 41 | colNames := make([]string, len(schema)) 42 | for c, col := range schema { 43 | colNames[c] = fmt.Sprintf("'%s'", col.Name) 44 | } 45 | 46 | sql, args, err := sq.Insert(inserter.table.name). 47 | Columns(colNames...). 48 | Values(row...). 49 | ToSql() 50 | if err != nil { 51 | return err 52 | } 53 | 54 | err = sqlitex.Exec(conn, sql, nil, args...) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | return nil 60 | } 61 | 62 | func (inserter *rowInserter) Close(*sql.Context) error { return nil } 63 | -------------------------------------------------------------------------------- /sqlitedb/row.go: -------------------------------------------------------------------------------- 1 | package sqlitedb 2 | 3 | import ( 4 | "io" 5 | 6 | "crawshaw.io/sqlite" 7 | "github.com/dolthub/go-mysql-server/sql" 8 | ) 9 | 10 | type queryResultRowIter struct { 11 | stmt *sqlite.Stmt 12 | closeFunc func() error 13 | } 14 | 15 | func newQueryResultRowIter(stmt *sqlite.Stmt, closeFunc func() error) *queryResultRowIter { 16 | return &queryResultRowIter{stmt: stmt, closeFunc: closeFunc} 17 | } 18 | 19 | func (iter *queryResultRowIter) Next() (sql.Row, error) { 20 | if hasNext, err := iter.stmt.Step(); err != nil { 21 | return nil, err 22 | } else if !hasNext { 23 | return nil, io.EOF 24 | } else { 25 | colCount := iter.stmt.ColumnCount() 26 | row := make([]interface{}, colCount) 27 | for c := 0; c < colCount; c++ { 28 | var tmp interface{} 29 | switch iter.stmt.ColumnType(c) { 30 | case sqlite.SQLITE_INTEGER: 31 | tmp = iter.stmt.ColumnInt64(c) 32 | case sqlite.SQLITE_FLOAT: 33 | tmp = iter.stmt.ColumnFloat(c) 34 | case sqlite.SQLITE_TEXT: 35 | tmp = iter.stmt.ColumnText(c) 36 | case sqlite.SQLITE_BLOB: 37 | buf := make([]byte, 1024*1024) // TODO(patrickdevivo) figure out a better value here? 38 | _ = iter.stmt.ColumnBytes(c, buf) 39 | case sqlite.SQLITE_NULL: 40 | tmp = nil 41 | } 42 | row[c] = tmp 43 | } 44 | return row, nil 45 | } 46 | } 47 | 48 | func (iter *queryResultRowIter) Close(*sql.Context) error { 49 | if err := iter.stmt.Reset(); err != nil { 50 | return err 51 | } 52 | if iter.closeFunc != nil { 53 | return iter.closeFunc() 54 | } else { 55 | return nil 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mergestat/go-mysql-sqlite-server 2 | 3 | go 1.17 4 | 5 | require ( 6 | crawshaw.io/sqlite v0.3.2 7 | github.com/Masterminds/squirrel v1.5.2 8 | github.com/dolthub/go-mysql-server v0.11.0 9 | github.com/dolthub/vitess v0.0.0-20211013185428-a8845fb919c1 10 | ) 11 | 12 | require ( 13 | github.com/cespare/xxhash v1.1.0 // indirect 14 | github.com/davecgh/go-spew v1.1.1 // indirect 15 | github.com/go-kit/kit v0.12.0 // indirect 16 | github.com/golang/glog v1.0.0 // indirect 17 | github.com/golang/protobuf v1.5.2 // indirect 18 | github.com/google/uuid v1.3.0 // indirect 19 | github.com/hashicorp/golang-lru v0.5.4 // indirect 20 | github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect 21 | github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect 22 | github.com/lestrrat-go/strftime v1.0.5 // indirect 23 | github.com/mitchellh/hashstructure v1.1.0 // indirect 24 | github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect 25 | github.com/opentracing/opentracing-go v1.2.0 // indirect 26 | github.com/pkg/errors v0.9.1 // indirect 27 | github.com/pmezard/go-difflib v1.0.0 // indirect 28 | github.com/shopspring/decimal v1.3.1 // indirect 29 | github.com/sirupsen/logrus v1.8.1 // indirect 30 | github.com/src-d/go-oniguruma v1.1.0 // indirect 31 | github.com/stretchr/testify v1.7.0 // indirect 32 | golang.org/x/net v0.0.0-20211206223403-eba003a116a9 // indirect 33 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect 34 | golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect 35 | google.golang.org/genproto v0.0.0-20211206220100-3cb06788ce7f // indirect 36 | google.golang.org/grpc v1.42.0 // indirect 37 | google.golang.org/protobuf v1.27.1 // indirect 38 | gopkg.in/src-d/go-errors.v1 v1.0.0 // indirect 39 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 40 | ) 41 | -------------------------------------------------------------------------------- /sqlitedb_test/sqlitedb_test.go: -------------------------------------------------------------------------------- 1 | package sqlitedb_test 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strings" 7 | "testing" 8 | 9 | "crawshaw.io/sqlite/sqlitex" 10 | "github.com/dolthub/go-mysql-server/enginetest" 11 | "github.com/dolthub/go-mysql-server/sql" 12 | "github.com/mergestat/go-mysql-sqlite-server/sqlitedb" 13 | ) 14 | 15 | type SQLiteDBHarness struct { 16 | *testing.T 17 | parallelism int 18 | } 19 | 20 | func NewSQLiteDBHarness(t *testing.T, parallelism int) *SQLiteDBHarness { 21 | return &SQLiteDBHarness{T: t, parallelism: parallelism} 22 | } 23 | 24 | func (harness *SQLiteDBHarness) Parallelism() int { return harness.parallelism } 25 | 26 | func (harness *SQLiteDBHarness) NewDatabase(name string) sql.Database { 27 | name = strings.ToLower(name) 28 | pool, err := sqlitex.Open(fmt.Sprintf("file:%s?mode=memory&cache=shared", name), 0, 10) 29 | if err != nil { 30 | harness.Fatal(err) 31 | } 32 | return sqlitedb.NewDatabase(name, pool, nil) 33 | } 34 | 35 | func (harness *SQLiteDBHarness) NewDatabases(names ...string) []sql.Database { 36 | dbs := make([]sql.Database, len(names)) 37 | for i, name := range names { 38 | name = strings.ToLower(name) 39 | dbs[i] = harness.NewDatabase(name) 40 | } 41 | return dbs 42 | } 43 | 44 | func (harness *SQLiteDBHarness) NewDatabaseProvider(dbs ...sql.Database) sql.MutableDatabaseProvider { 45 | return sqlitedb.NewProvider(dbs...) 46 | } 47 | 48 | func (harness *SQLiteDBHarness) NewTable(db sql.Database, name string, schema sql.Schema) (sql.Table, error) { 49 | name = strings.ToLower(name) 50 | 51 | sqliteBackedDB, ok := db.(*sqlitedb.Database) 52 | if !ok { 53 | return nil, errors.New("provided sql.Database not a *sqlitedb.Database") 54 | } 55 | 56 | if err := sqliteBackedDB.CreateTable(sql.NewEmptyContext(), name, schema); err != nil { 57 | return nil, err 58 | } 59 | 60 | return sqlitedb.NewTable(name, sqliteBackedDB), nil 61 | } 62 | 63 | func (harness *SQLiteDBHarness) NewContext() *sql.Context { 64 | return sql.NewEmptyContext() 65 | } 66 | 67 | func TestQueriesSimple(t *testing.T) { 68 | harness := NewSQLiteDBHarness(t, 1) 69 | // enginetest.TestCreateTable(t, harness) 70 | enginetest.TestQueries(t, harness) 71 | } 72 | -------------------------------------------------------------------------------- /sqlitedb/database_provider.go: -------------------------------------------------------------------------------- 1 | package sqlitedb 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strings" 7 | "sync" 8 | 9 | "crawshaw.io/sqlite/sqlitex" 10 | "github.com/dolthub/go-mysql-server/sql" 11 | ) 12 | 13 | var _ sql.DatabaseProvider = &provider{} 14 | var _ sql.MutableDatabaseProvider = &provider{} 15 | 16 | type provider struct { 17 | mut sync.RWMutex 18 | databases map[string]*Database 19 | } 20 | 21 | func NewProvider(dbs ...sql.Database) *provider { 22 | databases := make(map[string]*Database, len(dbs)) 23 | for _, db := range dbs { 24 | db, ok := db.(*Database) 25 | if !ok { 26 | continue 27 | } 28 | databases[strings.ToLower(db.Name())] = db 29 | } 30 | return &provider{ 31 | databases: databases, 32 | } 33 | } 34 | 35 | func (p *provider) Database(name string) (sql.Database, error) { 36 | p.mut.RLock() 37 | defer p.mut.RUnlock() 38 | name = strings.ToLower(name) 39 | 40 | if db, ok := p.databases[name]; !ok { 41 | return nil, sql.ErrDatabaseNotFound.New() 42 | } else { 43 | return db, nil 44 | } 45 | } 46 | 47 | func (p *provider) HasDatabase(name string) bool { 48 | p.mut.RLock() 49 | defer p.mut.RUnlock() 50 | name = strings.ToLower(name) 51 | 52 | _, ok := p.databases[name] 53 | return ok 54 | } 55 | 56 | func (p *provider) AllDatabases() []sql.Database { 57 | p.mut.RLock() 58 | defer p.mut.RUnlock() 59 | 60 | all := make([]sql.Database, len(p.databases)) 61 | var i int 62 | for _, db := range p.databases { 63 | all[i] = db 64 | i++ 65 | } 66 | 67 | sort.Slice(all, func(i, j int) bool { 68 | return all[i].Name() < all[j].Name() 69 | }) 70 | 71 | return all 72 | } 73 | 74 | func (p *provider) CreateDatabase(ctx *sql.Context, name string) error { 75 | p.mut.Lock() 76 | defer p.mut.Unlock() 77 | name = strings.ToLower(name) 78 | 79 | pool, err := sqlitex.Open(fmt.Sprintf("file:%s?mode=memory&cache=shared", name), 0, 10) 80 | if err != nil { 81 | return err 82 | } 83 | p.databases[name] = NewDatabase(name, pool, nil) 84 | return nil 85 | } 86 | 87 | func (p *provider) DropDatabase(ctx *sql.Context, name string) error { 88 | p.mut.Lock() 89 | defer p.mut.Unlock() 90 | name = strings.ToLower(name) 91 | 92 | delete(p.databases, name) 93 | return nil 94 | } 95 | -------------------------------------------------------------------------------- /sqlitedb/utils.go: -------------------------------------------------------------------------------- 1 | package sqlitedb 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strconv" 7 | "text/template" 8 | 9 | "github.com/dolthub/go-mysql-server/sql" 10 | "github.com/dolthub/vitess/go/vt/sqlparser" 11 | ) 12 | 13 | // mustInferType receives a MySQL type name, and resolves it to a sql.Type, or panics if it cannot. 14 | // It's a little odd how it does it - it creates a dummy `CREATE TABLE` statement with a single column 15 | // of the supplied type. It uses the vitess sql parser to turn the statement into an AST 16 | // (which will be of a known structure) and type-asserts it into the DDL node to retrieve the sqlparser.ColumnType. 17 | // This is allso so that we can use sql.ColumnTypeToType to resolve to a sql.Type 18 | func mustInferType(typeName string) sql.Type { 19 | stmt, err := sqlparser.Parse(fmt.Sprintf("CREATE TABLE t (c %s);", typeName)) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | parsed := stmt.(*sqlparser.DDL) 25 | if t, err := sql.ColumnTypeToType(&parsed.TableSpec.Columns[0].Type); err != nil { 26 | panic(err) 27 | } else { 28 | return t 29 | } 30 | } 31 | 32 | func createTableSQL(tableName string, schema sql.Schema) (string, error) { 33 | const declare = `CREATE TABLE {{ .TableName }} ( 34 | {{- range $c, $col := .Columns }} 35 | {{ quote .Name }} {{ colType $c }}{{ if notNull $c }} NOT NULL{{ end }}{{ if columnComma $c }},{{ end }} 36 | {{- end }} 37 | )` 38 | 39 | // helper to determine whether we're on the last column (and therefore should avoid a comma ",") in the range 40 | fns := template.FuncMap{ 41 | "columnComma": func(c int) bool { 42 | return c < len(schema)-1 43 | }, 44 | "colType": func(colIndex int) string { 45 | return schema[colIndex].Type.String() 46 | }, 47 | "notNull": func(colIndex int) bool { 48 | return !schema[colIndex].Nullable 49 | }, 50 | "quote": strconv.Quote, 51 | } 52 | 53 | tmpl, err := template.New(fmt.Sprintf("declare_table_func_%s", tableName)).Funcs(fns).Parse(declare) 54 | if err != nil { 55 | return "", err 56 | } 57 | 58 | buf := new(bytes.Buffer) 59 | err = tmpl.Execute(buf, struct { 60 | TableName string 61 | Columns sql.Schema 62 | }{ 63 | tableName, 64 | schema, 65 | }) 66 | if err != nil { 67 | return "", err 68 | } 69 | 70 | return buf.String(), nil 71 | } 72 | -------------------------------------------------------------------------------- /sqlitedb/table.go: -------------------------------------------------------------------------------- 1 | package sqlitedb 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/dolthub/go-mysql-server/sql" 8 | ) 9 | 10 | type Table struct { 11 | name string 12 | db *Database 13 | } 14 | 15 | func NewTable(name string, db *Database) *Table { 16 | return &Table{ 17 | name: name, 18 | db: db, 19 | } 20 | } 21 | 22 | func (t *Table) Name() string { return t.name } 23 | func (t *Table) String() string { return t.name } 24 | 25 | func (t *Table) Schema() sql.Schema { 26 | conn := t.db.pool.Get(context.TODO()) 27 | if conn == nil { 28 | //TODO(patrickdevivo) how should we handle error here? 29 | return nil 30 | } 31 | defer t.db.pool.Put(conn) 32 | 33 | schema := make([]*sql.Column, 0) 34 | 35 | // TODO(patrickdevivo) not sure if this is okay to do, the Sprintf 36 | // to use the table name in the SQL query. SQLite won't allow param binding in PRAGMA args 37 | // https://stackoverflow.com/questions/39985599/parameter-binding-not-working-for-sqlite-pragma-table-info 38 | // Maybe the table name string should be checked/escaped before use? 39 | stmt := conn.Prep(fmt.Sprintf("SELECT * FROM PRAGMA_TABLE_INFO('%s')", t.name)) 40 | for { 41 | if hasRow, err := stmt.Step(); err != nil { 42 | // TODO(patrickdevivo) how do we handle the error here? 43 | return nil 44 | } else if !hasRow { 45 | break 46 | } 47 | 48 | col := &sql.Column{ 49 | Name: stmt.GetText("name"), 50 | Type: mustInferType(stmt.GetText("type")), 51 | Default: nil, 52 | AutoIncrement: false, 53 | Nullable: stmt.GetInt64("notnull") == 0, 54 | Source: t.Name(), 55 | PrimaryKey: stmt.GetInt64("pk") == 1, 56 | } 57 | schema = append(schema, col) 58 | } 59 | 60 | return schema 61 | } 62 | 63 | func (t *Table) Partitions(ctx *sql.Context) (sql.PartitionIter, error) { 64 | return &singlePartitionIter{}, nil 65 | } 66 | 67 | func (t *Table) PartitionRows(ctx *sql.Context, _ sql.Partition) (sql.RowIter, error) { 68 | conn := t.db.pool.Get(ctx) 69 | if conn == nil { 70 | return nil, ErrNoSQLiteConn 71 | } 72 | 73 | stmt := conn.Prep(fmt.Sprintf("SELECT * FROM %s", t.Name())) 74 | closeFunc := func() error { 75 | t.db.pool.Put(conn) 76 | return nil 77 | } 78 | 79 | return newQueryResultRowIter(stmt, closeFunc), nil 80 | } 81 | -------------------------------------------------------------------------------- /sqlitedb/database.go: -------------------------------------------------------------------------------- 1 | package sqlitedb 2 | 3 | import ( 4 | "crawshaw.io/sqlite/sqlitex" 5 | "github.com/dolthub/go-mysql-server/sql" 6 | ) 7 | 8 | // Database is an implementation of a go-mysql-server database 9 | // backed by a SQLite database. 10 | type Database struct { 11 | name string 12 | pool *sqlitex.Pool 13 | options *DatabaseOptions 14 | } 15 | 16 | // DatabaseOptions are options for managing the SQLite backend 17 | type DatabaseOptions struct { 18 | // PreventInserts will block table insertions 19 | PreventInserts bool 20 | // PreventCreateTable will block table creation 21 | PreventCreateTable bool 22 | } 23 | 24 | func NewDatabase(name string, pool *sqlitex.Pool, options *DatabaseOptions) *Database { 25 | if options == nil { 26 | options = &DatabaseOptions{} 27 | } 28 | return &Database{name: name, pool: pool, options: options} 29 | } 30 | 31 | func (db *Database) Name() string { 32 | return db.name 33 | } 34 | 35 | func (db *Database) GetTableInsensitive(ctx *sql.Context, tblName string) (sql.Table, bool, error) { 36 | conn := db.pool.Get(ctx) 37 | if conn == nil { 38 | return nil, false, ErrNoSQLiteConn 39 | } 40 | defer db.pool.Put(conn) 41 | 42 | stmt := conn.Prep("SELECT name FROM sqlite_master WHERE type='table' AND name=$name COLLATE NOCASE;") 43 | stmt.SetText("$name", tblName) 44 | 45 | if hasRow, err := stmt.Step(); err != nil { 46 | return nil, false, err 47 | } else if !hasRow { 48 | return nil, false, nil 49 | } 50 | 51 | if err := stmt.Reset(); err != nil { 52 | return nil, false, err 53 | } 54 | 55 | return NewTable(tblName, db), true, nil 56 | } 57 | 58 | func (db *Database) GetTableNames(ctx *sql.Context) ([]string, error) { 59 | conn := db.pool.Get(ctx) 60 | if conn == nil { 61 | return nil, ErrNoSQLiteConn 62 | } 63 | defer db.pool.Put(conn) 64 | 65 | tables := make([]string, 0) 66 | stmt := conn.Prep("SELECT name FROM sqlite_master WHERE type='table'") 67 | for { 68 | if hasRow, err := stmt.Step(); err != nil { 69 | return nil, err 70 | } else if !hasRow { 71 | break 72 | } 73 | tables = append(tables, stmt.GetText("name")) 74 | } 75 | 76 | return tables, nil 77 | } 78 | 79 | func (db *Database) CreateTable(ctx *sql.Context, name string, schema sql.Schema) error { 80 | if db.options.PreventCreateTable { 81 | return ErrNoCreateTableAllowed 82 | } 83 | 84 | conn := db.pool.Get(ctx) 85 | if conn == nil { 86 | return ErrNoSQLiteConn 87 | } 88 | defer db.pool.Put(conn) 89 | 90 | sql, err := createTableSQL(name, schema) 91 | if err != nil { 92 | return err 93 | } 94 | 95 | if err := sqlitex.Exec(conn, sql, nil); err != nil { 96 | return err 97 | } 98 | 99 | return nil 100 | } 101 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | crawshaw.io/iox v0.0.0-20181124134642-c51c3df30797 h1:yDf7ARQc637HoxDho7xjqdvO5ZA2Yb+xzv/fOnnvZzw= 4 | crawshaw.io/iox v0.0.0-20181124134642-c51c3df30797/go.mod h1:sXBiorCo8c46JlQV3oXPKINnZ8mcqnye1EkVkqsectk= 5 | crawshaw.io/sqlite v0.3.2 h1:N6IzTjkiw9FItHAa0jp+ZKC6tuLzXqAYIv+ccIWos1I= 6 | crawshaw.io/sqlite v0.3.2/go.mod h1:igAO5JulrQ1DbdZdtVq48mnZUBAPOeFzer7VhDWNtW4= 7 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 8 | github.com/Masterminds/squirrel v1.5.2 h1:UiOEi2ZX4RCSkpiNDQN5kro/XIBpSRk9iTqdIRPzUXE= 9 | github.com/Masterminds/squirrel v1.5.2/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= 10 | github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= 11 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 12 | github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= 13 | github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= 14 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 15 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 16 | github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 17 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 18 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 19 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 20 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 21 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 22 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 23 | github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 24 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 25 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 26 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 27 | github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 28 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 29 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 30 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 31 | github.com/dolthub/go-mysql-server v0.11.0 h1:5DRlpwmFyFK35rI6Gj36CTqkxjQMFvPAAep92YcvD3U= 32 | github.com/dolthub/go-mysql-server v0.11.0/go.mod h1:+XgR49p1y6TGpVpjbmd23Ljpqr4L/06nNpf39TcP56M= 33 | github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81/go.mod h1:siLfyv2c92W1eN/R4QqG/+RjjX5W2+gCTRjZxBjI3TY= 34 | github.com/dolthub/vitess v0.0.0-20211013185428-a8845fb919c1 h1:4rbZqMa5Cq8O4ZLtOKwYCDvIC6joJRq9HLEpxO37bMQ= 35 | github.com/dolthub/vitess v0.0.0-20211013185428-a8845fb919c1/go.mod h1:hUE8oSk2H5JZnvtlLBhJPYC8WZCA5AoSntdLTcBvdBM= 36 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 37 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 38 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 39 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 40 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= 41 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 42 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 43 | github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw= 44 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 45 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 46 | github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= 47 | github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= 48 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 49 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 50 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 51 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 52 | github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= 53 | github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= 54 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 55 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 56 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 57 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 58 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 59 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 60 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 61 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 62 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 63 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 64 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 65 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 66 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 67 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 68 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 69 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 70 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 71 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 72 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 73 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 74 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 75 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 76 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 77 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 78 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 79 | github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 80 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 81 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 82 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 83 | github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 84 | github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= 85 | github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 86 | github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= 87 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 88 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 89 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 90 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 91 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 92 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 93 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 94 | github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= 95 | github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= 96 | github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= 97 | github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= 98 | github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= 99 | github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= 100 | github.com/lestrrat-go/strftime v1.0.1/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= 101 | github.com/lestrrat-go/strftime v1.0.5 h1:A7H3tT8DhTz8u65w+JRpiBxM4dINQhUXAZnhBa2xeOE= 102 | github.com/lestrrat-go/strftime v1.0.5/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= 103 | github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= 104 | github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0= 105 | github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA= 106 | github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 h1:Yl0tPBa8QPjGmesFh1D0rDy+q1Twx6FyU7VWHi8wZbI= 107 | github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852/go.mod h1:eqOVx5Vwu4gd2mmMZvVZsgIqNSaW3xxRThUJ0k/TPk4= 108 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 109 | github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= 110 | github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= 111 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 112 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 113 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 114 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 115 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 116 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 117 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 118 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 119 | github.com/sanity-io/litter v1.2.0 h1:DGJO0bxH/+C2EukzOSBmAlxmkhVMGqzvcx/rvySYw9M= 120 | github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4= 121 | github.com/shopspring/decimal v0.0.0-20191130220710-360f2bc03045/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= 122 | github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= 123 | github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= 124 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 125 | github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= 126 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 127 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= 128 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 129 | github.com/src-d/go-oniguruma v1.1.0 h1:EG+Nm5n2JqWUaCjtM0NtutPxU7ZN5Tp50GWrrV8bTww= 130 | github.com/src-d/go-oniguruma v1.1.0/go.mod h1:chVbff8kcVtmrhxtZ3yBVLLquXbzCS6DrxQaAK/CeqM= 131 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 132 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 133 | github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 134 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 135 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 136 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 137 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 138 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 139 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 140 | github.com/tebeka/strftime v0.1.4/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ= 141 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 142 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 143 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 144 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 145 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 146 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 147 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 148 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 149 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 150 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 151 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 152 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 153 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 154 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 155 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 156 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 157 | golang.org/x/net v0.0.0-20190926025831-c00fd9afed17/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 158 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 159 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 160 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 161 | golang.org/x/net v0.0.0-20211206223403-eba003a116a9 h1:HhGRSJWlxVO54+s9MeOVrZrbnwv+6oZQIvsUrMUte7U= 162 | golang.org/x/net v0.0.0-20211206223403-eba003a116a9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 163 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 164 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 165 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 166 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 167 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 168 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 169 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 170 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 171 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 172 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 173 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 174 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 175 | golang.org/x/sys v0.0.0-20190926180325-855e68c8590b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 176 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 177 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 178 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 179 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 180 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 181 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 182 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 183 | golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= 184 | golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 185 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 186 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 187 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 188 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 189 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 190 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 191 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 192 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 193 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 194 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 195 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 196 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 197 | golang.org/x/tools v0.0.0-20190830154057-c17b040389b9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 198 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 199 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 200 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 201 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 202 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 203 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 204 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 205 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 206 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 207 | google.golang.org/genproto v0.0.0-20190926190326-7ee9db18f195/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 208 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 209 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 210 | google.golang.org/genproto v0.0.0-20211206220100-3cb06788ce7f h1:QH7+Ym+7e2XV1dZIHapkXoeqHyNaCzn6MNp3JBaYYUc= 211 | google.golang.org/genproto v0.0.0-20211206220100-3cb06788ce7f/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 212 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 213 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 214 | google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= 215 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 216 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 217 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 218 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 219 | google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 220 | google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= 221 | google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 222 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 223 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 224 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 225 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 226 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 227 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 228 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 229 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 230 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 231 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 232 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 233 | google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 234 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 235 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 236 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 237 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 238 | gopkg.in/src-d/go-errors.v1 v1.0.0 h1:cooGdZnCjYbeS1zb1s6pVAAimTdKceRrpn7aKOnNIfc= 239 | gopkg.in/src-d/go-errors.v1 v1.0.0/go.mod h1:q1cBlomlw2FnDBDNGlnh6X0jPihy+QxZfMMNxPCbdYg= 240 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 241 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 242 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 243 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 244 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 245 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 246 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 247 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 248 | --------------------------------------------------------------------------------