Documentation ¶
Overview ¶
Package sqlittle/db provides low level access to SQLite (version 3) database files.
See ../README.md for general information about SQLittle, and see ../LOWLEVEL.md for information about this package.
Index ¶
- Constants
- Variables
- func Equals(key Key, r Record) bool
- func Fuzz(data []byte) int
- func Search(key Key, r Record) bool
- type Database
- func (db *Database) Close() error
- func (db *Database) Index(name string) (*Index, error)
- func (db *Database) Indexes() ([]string, error)
- func (db *Database) Info() (string, error)
- func (db *Database) NonRowidTable(name string) (*Index, error)
- func (db *Database) RLock() error
- func (db *Database) RUnlock() error
- func (db *Database) Schema(table string) (*Schema, error)
- func (db *Database) Table(name string) (*Table, error)
- func (db *Database) Tables() ([]string, error)
- type Index
- type IndexColumn
- type Key
- type KeyCol
- type Record
- type RecordCB
- type Schema
- type SchemaIndex
- type Table
- type TableColumn
- type TableScanCB
Examples ¶
Constants ¶
const ( // CachePages is the number of pages to keep in memory. Default size per // page is 4K (1K on older databases). CachePages = 100 )
Variables ¶
var ( // Various error messages returned when the database is corrupted ErrInvalidMagic = errors.New("invalid magic number") ErrInvalidPageSize = errors.New("invalid page size") ErrReservedSpace = errors.New("unsupported database (encrypted?)") ErrCorrupted = errors.New("database corrupted") ErrInvalidDef = errors.New("invalid object definition") ErrRecursion = errors.New("tree is too deep") // Various error messages returned when the database uses features sqlittle // doesn't support. ErrIncompatible = errors.New("incompatible database version") ErrEncoding = errors.New("unsupported encoding") // Database is in WAL journal mode, which we don't support. You need to // convert the database to journal mode. ErrWAL = errors.New("WAL journal mode is unsupported") // There is a stale `-journal` file present with an unfinished transaction. // Open the database in sqlite3 to repair the database. ErrHotJournal = errors.New("crashed transaction present") ErrNoSuchTable = errors.New("no such table") ErrNoSuchIndex = errors.New("no such index") )
var CollateFuncs = map[string]func(string, string) int{ "binary": strings.Compare, "rtrim": func(a, b string) int { return strings.Compare( strings.TrimRight(a, " \t\r\n"), strings.TrimRight(b, " \t\r\n"), ) }, "nocase": func(a, b string) int { lc := func(r rune) rune { if r >= 'A' && r <= 'Z' { return rune(strings.ToLower(string(r))[0]) } return r } return strings.Compare( strings.Map(lc, a), strings.Map(lc, b), ) }, }
available collate functions
var DefaultCollate = "binary"
Functions ¶
Types ¶
type Database ¶
type Database struct {
// contains filtered or unexported fields
}
func OpenFile ¶
OpenFile opens a .sqlite file. This is the main entry point. Use database.Close() when done.
func (*Database) Index ¶
Index opens the named index. Will return ErrNoSuchIndex when the index isn't there (or isn't an index). Index pointer is always valid if err == nil.
Indexes work for normal and WITHOUT ROWID tables. The columns the callback gets depends on the type of table.
func (*Database) NonRowidTable ¶
NonRowidTable open a `WITHOUT ROWID` table. It's implemented with an Index.
func (*Database) Schema ¶
Schema gives the definition of a table and all associated indexes.
Example ¶
db, err := OpenFile("../testdata/words.sqlite") if err != nil { panic(err) } defer db.Close() schema, err := db.Schema("words") if err != nil { panic(err) } fmt.Printf("columns:\n") for _, c := range schema.Columns { fmt.Printf(" - %q is a %s\n", c.Column, c.Type) } fmt.Printf("available indexes:\n") for _, ind := range schema.Indexes { fmt.Printf(" - %q (", ind.Index) for i, c := range ind.Columns { if i > 0 { fmt.Printf(", ") } fmt.Print(c.Column) } fmt.Print(")\n") }
Output: columns: - "word" is a varchar - "length" is a int available indexes: - "words_index_1" (word) - "words_index_2" (length, word)
type Index ¶
type Index struct {
// contains filtered or unexported fields
}
Index is either an index, or the table for a non-rowid table
func (*Index) Def ¶
func (t *Index) Def() (*sql.CreateIndexStmt, error)
Def returns the index definition.
func (*Index) Scan ¶
Scan calls cb() for every row in the index. These will be called in the index order. The callback gets the record as stored in the index. For indexes on a non-WITHOUT ROWID table the last value will be the rowid (see ChompRowid()). For a WITHOUT ROWID table the columns depend on your table structure. If the callback returns true (done) the scan will be stopped.
Example ¶
// This code will iterate over all words in alphabetical order. // The `words` table has: CREATE INDEX words_index_1 ON words (word) db, err := OpenFile("../testdata/words.sqlite") if err != nil { panic(err) } defer db.Close() index, err := db.Index("words_index_1") if err != nil { panic(err) } i := 0 if err := index.Scan( func(rec Record) bool { fmt.Printf("row %d: %s\n", rec[1].(int64), rec[0].(string)) i++ return i >= 10 }, ); err != nil { panic(err) }
Output: row 329: Adams row 123: Ahmadinejad row 870: Alabaman row 685: Algonquin row 619: Amy row 700: Andersen row 900: Annette's row 423: Antipas's row 891: Arizonan row 945: Artaxerxes's
func (*Index) ScanEq ¶
Scan all record matching key
Example ¶
// Find records matching a key. db, err := OpenFile("../testdata/words.sqlite") if err != nil { panic(err) } defer db.Close() index, err := db.Index("words_index_1") if err != nil { panic(err) } // match only wombat if err := index.ScanEq( Key{KeyCol{V: "wombat"}}, func(rec Record) bool { fmt.Printf("%v\n", rec) // word, rowid return false }, ); err != nil { panic(err) }
Output: [wombat 159]
func (*Index) ScanMin ¶
ScanMin calls cb() for every row in the index, starting from the first record where key is true.
If the callback returns true (done) the scan will be stopped. All comments from Index.Scan are valid here as well.
Example ¶
// This will iterate over all words in alphabetical order, starting from // the first record >= the given record. // The `words` table has: CREATE INDEX words_index_1 ON words (word) db, err := OpenFile("../testdata/words.sqlite") if err != nil { panic(err) } defer db.Close() index, err := db.Index("words_index_1") if err != nil { panic(err) } if err := index.ScanMin( Key{KeyCol{V: "wombat"}}, func(rec Record) bool { word := rec[0].(string) if word >= "y" { return true } fmt.Printf("%s\n", word) return false }, ); err != nil { panic(err) }
Output: wombat workbook world's worsens wristwatch's writhing wusses
func (*Index) ScanRange ¶
Find all records where from(index) is true, and to(index) is false.
You'll have to compensate for DESC columns.
Example ¶
// Find records matching a range db, err := OpenFile("../testdata/words.sqlite") if err != nil { panic(err) } defer db.Close() index, err := db.Index("words_index_1") if err != nil { panic(err) } // scan from wombat inclusive to wusses exclusive if err := index.ScanRange( Key{KeyCol{V: "wombat"}}, Key{KeyCol{V: "wusses"}}, func(rec Record) bool { fmt.Printf("%v\n", rec) // word, rowid return false }, ); err != nil { panic(err) }
Output: [wombat 159] [workbook 975] [world's 114] [worsens 770] [wristwatch's 491] [writhing 343]
type IndexColumn ¶
type Record ¶
type Record []interface{}
Record is a row in the database. It can only have fields of these types: nil, int64, float64, string, []byte
type RecordCB ¶
RecordCB is passed to Index.Scan(), Index.ScanMin(), and Table.ScanWithoutRowid. It should return true when the scan should be stopped.
For index scans: The callback gets the raw values as stored in the index. For a normal index the last value is the rowid value (see ChompRowid()). For a WITHOUT ROWID it depends on the table which rows there are.
type Schema ¶
type Schema struct { Table string WithoutRowid bool Columns []TableColumn Indexes []SchemaIndex PK []IndexColumn // only set for non-rowid tables PrimaryKey string // only set for rowid tables: name of the index RowidPK bool // only set for rowid tables: whether we have a 'integer primary key' column, which means there is no separate index for the primary key }
func (*Schema) NamedIndex ¶
func (st *Schema) NamedIndex(name string) *SchemaIndex
NamedIndex returns the index with the name (case insensitive)
type SchemaIndex ¶
type SchemaIndex struct { Index string Columns []IndexColumn }
func (*SchemaIndex) Column ¶
func (si *SchemaIndex) Column(name string) int
Returns the index of the named column, or -1.
type Table ¶
type Table struct {
// contains filtered or unexported fields
}
func (*Table) Def ¶
func (t *Table) Def() (*sql.CreateTableStmt, error)
Def returns the table definition. Not everything SQLite supports is supported (yet). See Database.Schema() for a friendlier interface.
Example ¶
db, err := OpenFile("../testdata/words.sqlite") if err != nil { panic(err) } defer db.Close() index, err := db.Index("words_index_2") if err != nil { panic(err) } ind, err := index.Def() if err != nil { panic(err) } for _, c := range ind.IndexedColumns { fmt.Printf("indexed column: %q (sortorder %s)\n", c.Column, c.SortOrder) }
Output: indexed column: "length" (sortorder ASC) indexed column: "word" (sortorder ASC)
func (*Table) Rowid ¶
Rowid finds a single row by rowid. Will return nil if it isn't found. The rowid is an internal id, but if you have an `integer primary key` column that should be the same. See Table.Scan comments about the Record
Example ¶
db, err := OpenFile("../testdata/single.sqlite") if err != nil { panic(err) } defer db.Close() table, err := db.Table("hello") if err != nil { panic(err) } row, err := table.Rowid(2) if err != nil { panic(err) } fmt.Printf("row: %s\n", row[0].(string))
Output: row: universe
Example (Nonrowid) ¶
db, err := OpenFile("../testdata/withoutrowid.sqlite") if err != nil { panic(err) } defer db.Close() table, err := db.NonRowidTable("words") if err != nil { panic(err) } if err := table.ScanEq( Key{KeyCol{V: "awesomely"}}, func(r Record) bool { fmt.Printf("row: %v\n", r) return false }, ); err != nil { panic(err) }
Output: row: [awesomely 9]
func (*Table) Scan ¶
func (t *Table) Scan(cb TableScanCB) error
Scan calls cb() for every row in the table. Will be called in 'database order'. The record is given as sqlite stores it; this means:
- float64 columns might be stored as int64
- after an alter table which adds columns a row might miss the new columns
- an "integer primary key" column will be always be nil, and the rowid is the value
If the callback returns true (done) the scan will be stopped.
Example ¶
db, err := OpenFile("../testdata/single.sqlite") if err != nil { panic(err) } defer db.Close() table, err := db.Table("hello") if err != nil { panic(err) } if err := table.Scan( func(rowid int64, rec Record) bool { fmt.Printf("row %d: %s\n", rowid, rec[0].(string)) return false // we want all the rows }, ); err != nil { panic(err) }
Output: row 1: world row 2: universe row 3: town
Example (Nonrowid) ¶
db, err := OpenFile("../testdata/withoutrowid.sqlite") if err != nil { panic(err) } defer db.Close() table, err := db.NonRowidTable("words") if err != nil { panic(err) } i := 10 if err := table.Scan( func(rec Record) bool { fmt.Printf("row %s\n", rec[0].(string)) i-- return i <= 0 }, ); err != nil { panic(err) }
Output: row Adams row Ahmadinejad row Alabaman row Algonquin row Amy row Andersen row Annette's row Antipas's row Arizonan row Artaxerxes's
type TableColumn ¶
type TableScanCB ¶
TableScanCB is the callback for Table.Scan(). It gets the rowid (usually an internal number), and the data of the row. It should return true when the scan should be terminated.