I never thought I be doing this again, and yet, here we are! Join me in the adventures of "oh god we are installing windows 98 again" pic.twitter.com/Ub83PQ4sV7
65 |
66 |
67 | 
68 |
69 | The search engine works:
70 |
71 | 
72 |
73 | As NeoZeed found out, the search interface only listens on loopback (hardcoded), which is very annoying if you want to expose it to the wider world! To solve this [stunnel](https://www.stunnel.org/index.html)
74 | was deployed to listen on * and relay connections back to the local instance, with added SSL! [Using a pretty questionable (but CT logged) default SSL certificate too](https://crt.sh/?id=130496527) [(A)](http://archive.is/WJNYb)!
75 |
76 | ## Providing data to the indexer
77 |
78 | Because the indexer and backend is a Windows 98 QEMU VM, there has to be a way of giving that VM approximately 5GB of tiny files for the AltaVista indexer to see and include in the index. For this, I chose to make a FAT32 file system every 24 hours as a snapshot of the crawled data, and then restart the crawling VM to see the new files. This worked really quite well in testing with a small amount of files, however a few issues became apparent: first of all FAT32 has file limits that need to be paid attention to. For example, FAT32 is not able to have more than 255 files in the root directory, so you have to be sure to spread out your files in folder structures.
79 |
80 | Another issue to keep in mind is that the maximum drive size for FAT32 is 32GB (approx). This means the amount of textual content can't go bigger than that (or we would have to spawn more virtual drives). Fortunately, the size of the crawled content is far below that so this is a non issue.
81 |
82 | While crawling a "production size" data set, the system would reset at a random point during the indexing program running:
83 |
84 | 
85 |
86 | After tweaking the settings involving the disk caches, a slightly more constructive error was obtained:
87 |
88 | 
89 |
90 | This is good! I can search for `exception 05 has occurred at 0028:C2920074`! Right? As it happens, there is very little information about this kind of crash on the internet (it may have existed at some point in the past, but since been removed; after all, the OS is 20 years old), however the one piece of information I could gather from searching is that it was VFAT driver related. Suspecting a bad combo between high IO load and QEMU's [INT_13](https://en.wikipedia.org/wiki/INT_13H) implementation, I went for the only other file system/data input system available, CD/DVD ROM!
91 |
92 | After doing a small 500MB test (a test that FAT32 could not pass) we had a small index!
93 |
94 | 
95 |
96 | At this point we had to scale up the solution to the 300k / 4 GB of files. I discovered that Windows 98 does support DVDs, even though the UI can only display that the drive is 2GB, even if the drive is much larger than that. Despite that, all content was accessible on the drive and an initial index was (slowly) built.
97 |
98 | ## Sanitise the index interface
99 |
100 | The only problem with using a 20 year old indexer, is that it's likely a **very** bad idea to expose directly to the internet. The other issue is that on most of the pages the interface serves references local (as in, `file://`) assets, meaning that a simple reverse proxy would not work.
101 |
102 | In addition, local paths are not very useful to people searching. For this `alta-sanitise` was written to provide a sane front end to it, while still keeping the Windows 98 AltaVista index as it's backend.
103 |
104 | To do this, I produce a file system containing all the files that were downloaded, and name them by their database ID:
105 |
106 | 
107 |
108 | However in alta-sanitise, we use the database we formed using crawling, to rewrite the URL's into something viewable:
109 |
110 | 
111 |
112 | To ensure the VM could be used for more than one project, lighttpd was put in front as a reverse proxy of `alta-sanitise`, and Cloudflare used for cache. This leaves the final flow looking like this:
113 |
114 | 
115 |
116 | # Monitoring Windows 98
117 |
118 | Most of my servers are monitored using collectd. Unfortunately there is no Windows 98 client for collectd (!?), so I decided to make one.
119 |
120 | A simple Visual Basic 6 application will poll every 10 seconds and output [collectd command strings](https://collectd.org/wiki/index.php/Plain_text_protocol#PUTVAL) over the serial port (where it can be passed on to collectd on the hypervisor):
121 |
122 | 
123 |
124 | 
125 |
126 | This code can be found separately at: https://github.com/benjojo/win32-collectd
127 |
128 | (Some troubled soul may find this useful outside of a gopher crawler.)
129 |
130 | # Giving back to the community
131 |
132 | Now that I have a sizeable index of the gopher space, I feel like I should give back to gopher space:
133 |
134 | 
135 |
136 | You can now find my blog on gopher at `gopher.blog.benjojo.co.uk` (** only accessible on gopher, Lynx supports gopher if that helps **).
137 |
138 | The search engine can be used at: http://gophervista.benjojo.co.uk
139 |
140 | And the code can be found at: https://github.com/benjojo/gophervista
--------------------------------------------------------------------------------
/blog/bsod.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/bsod.png
--------------------------------------------------------------------------------
/blog/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/demo.png
--------------------------------------------------------------------------------
/blog/example-search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/example-search.png
--------------------------------------------------------------------------------
/blog/flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/flow.png
--------------------------------------------------------------------------------
/blog/grafana.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/grafana.png
--------------------------------------------------------------------------------
/blog/index-built.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/index-built.png
--------------------------------------------------------------------------------
/blog/installer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/installer.png
--------------------------------------------------------------------------------
/blog/random-crash.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/random-crash.gif
--------------------------------------------------------------------------------
/blog/rewritten-search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/rewritten-search.png
--------------------------------------------------------------------------------
/blog/simple-search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/simple-search.png
--------------------------------------------------------------------------------
/blog/tty-my-blog.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/tty-my-blog.gif
--------------------------------------------------------------------------------
/blog/tty-of-gopher.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/blog/tty-of-gopher.gif
--------------------------------------------------------------------------------
/crawler/crawl.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/base32"
5 | "fmt"
6 | "io/ioutil"
7 | "log"
8 | "os"
9 | "time"
10 |
11 | "github.com/benjojo/gophervista/rfc1436"
12 | )
13 |
14 | func crawl(Queue crawlerQueue, datadir string) {
15 | var workers map[string]chan string
16 | workers = make(map[string]chan string)
17 | indexn := 0
18 | skiphost := "impossibleaaaaaaaaaaaaaaaaaa"
19 |
20 | for {
21 | time.Sleep(time.Millisecond * 5)
22 | var asset string
23 | asset, indexn = Queue.GetItemToCrawlFromIndex(indexn, skiphost)
24 | if asset == "" {
25 | log.Print("Nothing to crawl...")
26 | indexn = 0
27 | continue
28 | }
29 | indexn++
30 |
31 | canCrawl, _ := Queue.CheckItemPerms(asset)
32 |
33 | if !canCrawl {
34 | log.Printf("Can't crawl %s because of restriction", asset)
35 | Queue.FlagItemAsCrawled(asset)
36 | continue
37 | }
38 |
39 | _, hn, _, err := rfc1436.ParseURI(asset)
40 | if err != nil {
41 | log.Printf("Invalid URI, %s", err.Error())
42 | continue
43 | }
44 |
45 | if workers[hn] == nil {
46 | ch := make(chan string, 1)
47 | workers[hn] = ch
48 | go crawlWorker(ch, Queue, datadir)
49 | go crawlerFeeder(ch, hn, Queue)
50 | }
51 | select {
52 | case workers[hn] <- asset: // ignore if it's full.
53 | skiphost = "impossibleaaaaaaaaaaa"
54 | default:
55 | skiphost = hn
56 | }
57 |
58 | }
59 | }
60 |
61 | func crawlerFeeder(assetChan chan string, hn string, Queue crawlerQueue) {
62 | indexn := 0
63 | totallydry := 0
64 |
65 | for {
66 | time.Sleep(time.Millisecond * 500)
67 | var asset string
68 | asset, indexn = Queue.GetItemToCrawlFromIndexFromHost(indexn, hn)
69 | if asset == "" {
70 | log.Printf("Nothing to crawl, Reseting pointer for %s", hn)
71 | indexn = 0
72 | totallydry++
73 | if totallydry > 1 {
74 | time.Sleep(time.Minute)
75 | log.Printf("Really lothing left to crawl for %s, Chilling back for a bit", hn)
76 | }
77 | continue
78 | }
79 | indexn++
80 |
81 | canCrawl, _ := Queue.CheckItemPerms(asset)
82 |
83 | if !canCrawl {
84 | log.Printf("Can't crawl %s because of restriction", asset)
85 | Queue.FlagItemAsCrawled(asset)
86 | continue
87 | }
88 |
89 | assetChan <- asset
90 | totallydry = 0
91 | }
92 | }
93 |
94 | func crawlWorker(assetChan chan string, Queue crawlerQueue, datadir string) {
95 | for asset := range assetChan {
96 | if asset == "" {
97 | log.Print("Nothing to crawl...")
98 | continue
99 | }
100 |
101 | _, canLearn := Queue.CheckItemPerms(asset)
102 |
103 | time.Sleep(time.Second)
104 |
105 | d, ci, err := rfc1436.Get(asset)
106 | log.Printf("Grabbing %s", asset)
107 | if err != nil {
108 | log.Printf("Failed to crawl '%s' - %s", asset, err.Error())
109 | Queue.FlagItemAsCrawled(asset)
110 | continue
111 | }
112 |
113 | storefolder := fmt.Sprintf("%s/raw/%s-%d/", datadir, ci.Hostname, ci.Port)
114 | err = os.MkdirAll(storefolder, 0755)
115 | if err != nil && err != os.ErrExist {
116 | log.Printf("Unable to make directory structure (%s) to store responce in, %s", storefolder, err.Error())
117 | }
118 |
119 | ioutil.WriteFile(storefolder+base32shortcut(asset), d.Raw, 0755)
120 |
121 | for _, ln := range d.Items {
122 | if ln.Type == rfc1436.TypeMenuEntity ||
123 | ln.Type == rfc1436.TypeTextFile {
124 | newpath := fmt.Sprintf("gopher://%s:%d%s", ln.Host, ln.Port, ln.Path)
125 | if canLearn {
126 | Queue.FlagItem(newpath, ln.Type)
127 | } else {
128 | log.Printf("Can't add %s to crawl list, Domain has restriction in place", newpath)
129 | }
130 | }
131 | }
132 | Queue.FlagItemAsCrawled(asset)
133 | }
134 | }
135 |
136 | func base32shortcut(path string) string {
137 | return base32.StdEncoding.EncodeToString([]byte(path))
138 | }
139 |
--------------------------------------------------------------------------------
/crawler/database.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "database/sql"
5 | "fmt"
6 | "log"
7 | "regexp"
8 | "sync"
9 | "time"
10 | )
11 |
12 | type crawlerQueue struct {
13 | db *sql.DB
14 | dblock sync.Mutex
15 | flagchan chan FlagRequest
16 | }
17 |
18 | func (cq *crawlerQueue) Init(databasepath string) error {
19 | db, err := sql.Open("sqlite3", databasepath)
20 | if err != nil {
21 | return err
22 | }
23 |
24 | err = db.Ping() // database do odd things
25 | if err != nil {
26 | return err
27 | }
28 |
29 | cq.db = db
30 |
31 | cq.maketableifnotexists("assets",
32 | "CREATE TABLE assets (id INTEGER PRIMARY KEY, timestamp NUMERIC, path TEXT, type TEXT, lastcrawled NUMERIC);")
33 |
34 | cq.maketableifnotexists("restrictions",
35 | "CREATE TABLE `restrictions` (`id` INTEGER,`pattern` TEXT,`nolearn` INTEGER DEFAULT 0,`nocrawl` INTEGER DEFAULT 0,PRIMARY KEY(id));")
36 |
37 | cq.flagchan = make(chan FlagRequest, 1)
38 | go cq.FlagChannelConsumer(cq.flagchan)
39 |
40 | return nil
41 | }
42 |
43 | func (cq *crawlerQueue) maketableifnotexists(table, makestring string) {
44 | tablename := ""
45 | cq.db.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", table).Scan(&tablename)
46 |
47 | if tablename != table {
48 | log.Printf("Made a new %s table", table)
49 | cq.db.Exec(makestring)
50 | }
51 |
52 | }
53 |
54 | func (cq *crawlerQueue) GetItemToCrawl() string {
55 | cq.dblock.Lock()
56 | defer cq.dblock.Unlock()
57 | asset := ""
58 | err := cq.db.QueryRow("SELECT path FROM assets WHERE lastcrawled < ? LIMIT 1", time.Now().Unix()-604800).Scan(&asset)
59 | if err != nil {
60 | return ""
61 | }
62 | return asset
63 | }
64 |
65 | func (cq *crawlerQueue) GetItemToCrawlFromIndex(indexin int, skiphost string) (asset string, index int) {
66 | cq.dblock.Lock()
67 | defer cq.dblock.Unlock()
68 | err := cq.db.QueryRow("SELECT path,id FROM assets WHERE lastcrawled < ? AND id > ? AND path NOT LIKE ? LIMIT 1",
69 | time.Now().Unix()-604800, indexin, fmt.Sprintf("%%%s%%", skiphost)).Scan(&asset, &index)
70 | if err != nil {
71 | return "", 0
72 | }
73 | return asset, index
74 | }
75 |
76 | func (cq *crawlerQueue) GetItemToCrawlFromIndexFromHost(indexin int, targethost string) (asset string, index int) {
77 | cq.dblock.Lock()
78 | defer cq.dblock.Unlock()
79 | err := cq.db.QueryRow("SELECT path,id FROM assets WHERE lastcrawled < ? AND id > ? AND path LIKE ? LIMIT 1",
80 | time.Now().Unix()-604800, indexin, fmt.Sprintf("%%%s%%", targethost)).Scan(&asset, &index)
81 | if err != nil {
82 | return "", 0
83 | }
84 | return asset, index
85 | }
86 |
87 | func (cq *crawlerQueue) FlagItemAsCrawled(path string) {
88 | _, err := cq.db.Exec("UPDATE assets SET lastcrawled = ? WHERE path = ?", time.Now().Unix(), path)
89 | if err != nil {
90 | log.Printf("Unable to flag asset as crawled? %s", err.Error())
91 | if err.Error() == "database is locked" { // aaaa a aaaa aaaaaaaa terrible i'm so sorry
92 | log.Printf("Retrying in a moment due to %s", err.Error())
93 | go func() {
94 | // Well we are already doing sins here, so what's one more?
95 | time.Sleep(time.Second)
96 | cq.FlagItemAsCrawled(path)
97 | }()
98 | }
99 | }
100 | }
101 |
102 | type FlagRequest struct {
103 | Path string
104 | GTypeStr string
105 | }
106 |
107 | func (cq *crawlerQueue) FlagItem(path string, gtypestr string) {
108 | cq.flagchan <- FlagRequest{
109 | Path: path,
110 | GTypeStr: gtypestr,
111 | }
112 | }
113 |
114 | func (cq *crawlerQueue) FlagChannelConsumer(in chan FlagRequest) {
115 | for rq := range in {
116 | cq.dblock.Lock()
117 | test := 0
118 | err := cq.db.QueryRow("SELECT COUNT(*) path FROM assets WHERE path = ?;", rq.Path).Scan(&test)
119 | if err != nil {
120 | log.Printf("Huh, unable to see if an item to be should be crawled - %s", err.Error())
121 | continue
122 | }
123 |
124 | if test == 0 {
125 | log.Printf("Found item to add %s", rq.Path)
126 |
127 | // Fantastic, We can add it
128 | _, err = cq.db.Exec("INSERT INTO `assets` (`id`,`timestamp`,`path`,`type`,`lastcrawled`) VALUES (NULL,?,?,?,0);", time.Now().Unix(), rq.Path, rq.GTypeStr)
129 | if err != nil {
130 | log.Printf("Huh, unable to flag to be should be crawled - %s", err.Error())
131 | continue
132 | }
133 | }
134 | cq.dblock.Unlock()
135 | }
136 | }
137 |
138 | type permissionRow struct {
139 | Pattern *regexp.Regexp
140 | CanLearn bool
141 | CanCrawl bool
142 | }
143 |
144 | var permissionsCache []permissionRow
145 |
146 | func (cq *crawlerQueue) CheckItemPerms(path string) (canCrawl bool, canLearn bool) {
147 | if len(permissionsCache) == 0 || permissionsCache == nil {
148 | log.Printf("Loading perms")
149 | permissionsCache = make([]permissionRow, 0)
150 | rows, err := cq.db.Query("SELECT pattern,nolearn,nocrawl FROM restrictions;")
151 | if err != nil {
152 | log.Fatalf("Unable to load crawling restrictions/perms, %s", err.Error())
153 | }
154 |
155 | for rows.Next() {
156 | var iCanLearn, iCanCrawl int
157 | var RERaw string
158 |
159 | err := rows.Scan(&RERaw, &canLearn, &canCrawl)
160 | if err != nil {
161 | log.Fatalf("Unable to process crawling restrictions/perms, %s", err.Error())
162 | }
163 |
164 | RE := regexp.MustCompile(RERaw)
165 |
166 | n := permissionRow{
167 | Pattern: RE,
168 | CanCrawl: iCanCrawl == 0,
169 | CanLearn: iCanLearn == 0,
170 | }
171 |
172 | permissionsCache = append(permissionsCache, n)
173 | }
174 | log.Printf("%d perm restrictions loaded", len(permissionsCache))
175 | }
176 |
177 | // Now that it's all loaded...
178 |
179 | for _, testcase := range permissionsCache {
180 | if testcase.Pattern.MatchString(path) {
181 | return !testcase.CanCrawl, !testcase.CanLearn
182 | }
183 | }
184 |
185 | return true, true
186 | }
187 |
--------------------------------------------------------------------------------
/crawler/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "log"
6 | "os"
7 |
8 | _ "github.com/mattn/go-sqlite3"
9 | )
10 |
11 | var (
12 | databasepath = flag.String("dbpath", "./crawl.db", "Where to store the metadata of crawling")
13 | datapath = flag.String("datadir", "./data", "where to download assets to")
14 | )
15 |
16 | func main() {
17 | flag.Parse()
18 |
19 | ledger := crawlerQueue{}
20 | err := ledger.Init(*databasepath)
21 | if err != nil {
22 | log.Fatalf("Unable to open database. %s", err.Error())
23 | }
24 |
25 | crawl(ledger, *datapath)
26 | os.Exit(1)
27 | }
28 |
--------------------------------------------------------------------------------
/filesystem-gen/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "database/sql"
5 | "encoding/base32"
6 | "flag"
7 | "fmt"
8 | "io"
9 | "log"
10 | "os"
11 | "path/filepath"
12 |
13 | _ "github.com/mattn/go-sqlite3"
14 | )
15 |
16 | func main() {
17 | dbpath := flag.String("dbpath", "./crawl.db", "Where to find the database")
18 | opath := flag.String("outputpath", "./cds/", "Where to put the folders")
19 | flag.Parse()
20 | log.Printf("Making filesystem...")
21 |
22 | db, err := sql.Open("sqlite3", *dbpath)
23 | if err != nil {
24 | log.Fatalf("unable to open db %s", err.Error())
25 | }
26 |
27 | err = db.Ping() // database do odd things
28 | if err != nil {
29 | log.Fatalf("unable to check db %s", err.Error())
30 | }
31 |
32 | filesmoved := 0
33 | cd := 0
34 | bytesOnDisk := 0
35 |
36 | os.MkdirAll(*opath+fmt.Sprint(cd)+"/0/", 0777)
37 |
38 | filepath.Walk("./data", func(path string, info os.FileInfo, err error) error {
39 | if err != nil {
40 | return nil
41 | }
42 | if info.IsDir() {
43 | return nil
44 | }
45 |
46 | encodedfilename := filepath.Base(path)
47 | gopherurl, err := base32.StdEncoding.DecodeString(encodedfilename)
48 | if err != nil {
49 | return nil
50 | }
51 |
52 | var dbid int
53 | err = db.QueryRow("SELECT id FROM assets WHERE path=? LIMIT 1", string(gopherurl)).Scan(&dbid)
54 |
55 | if err != nil || dbid == 0 {
56 | log.Printf("%s", err.Error())
57 | return nil
58 | }
59 |
60 | if bytesOnDisk > 1900000000 {
61 | bytesOnDisk = 0
62 | cd++
63 | os.MkdirAll(fmt.Sprintf("%s%d/", *opath, cd), 0777)
64 | }
65 | bytesOnDisk += int(info.Size())
66 |
67 | if filesmoved%1000 == 0 {
68 | os.MkdirAll(fmt.Sprintf("%s%d/%d/", *opath, cd, filesmoved/1000), 0777)
69 | }
70 |
71 | dstpath := fmt.Sprintf("%s%d/%d/%d.txt", *opath, cd, filesmoved/1000, dbid)
72 | err = copy(path, dstpath)
73 | if err != nil {
74 | log.Printf("failed to copy file over to %s - %s", dstpath, err.Error())
75 | }
76 |
77 | filesmoved++
78 |
79 | return nil
80 | })
81 | }
82 |
83 | func copy(src, dst string) error {
84 | in, err := os.Open(src)
85 | if err != nil {
86 | return err
87 | }
88 | defer in.Close()
89 | out, err := os.Create(dst)
90 | if err != nil {
91 | return err
92 | }
93 | defer out.Close()
94 | _, err = io.Copy(out, in)
95 | cerr := out.Close()
96 | if err != nil {
97 | return err
98 | }
99 | return cerr
100 | }
101 |
--------------------------------------------------------------------------------
/filesystem-gen/mkfs.sh:
--------------------------------------------------------------------------------
1 | #/bin/bash
2 | set -e
3 |
4 | cp crawl.db snapshot.db
5 |
6 | # if ! df -h | grep -Fq loop0; then
7 | # echo "Need to make FS"
8 | # losetup -d /dev/loop0 || echo "Non fatal, continuing"
9 | # dd if=/dev/zero of=filesystem.img bs=1 count=0 seek=8G
10 | # sfdisk filesystem.img < filesystem-gen/layout.sfdisk
11 | # losetup /dev/loop0 filesystem.img
12 | # mkfs.fat /dev/loop0p1
13 | # mkdir fat32 || echo "Unable to make fat32 dir, probs because it exists"
14 | # mount /dev/loop0p1 ./fat32/
15 | # fi
16 |
17 | mkdir fat32 || echo "Non fatal, continuing"
18 |
19 | cd fat32 && rm -r * || echo "wasnt able to remove things in the FS, probs because it was empty anyway"
20 |
21 | # # Zero out the drive so that it compresses better
22 | # for i in {1..8}
23 | # do
24 | # dd if=/dev/zero of=$i.stuff bs=1 count=0 seek=1G || echo "."
25 | # done
26 | # rm *.stuff
27 | # cd ..
28 | ./bin/filesystem-gen -dbpath snapshot.db
29 | #umount ./fat32
30 | #losetup -d /dev/loop0
31 | #qemu-img convert -O qcow2 filesystem.img image.qcow2
32 | rm mega.iso || echo "."
33 | xorrisofs -o mega.iso fat32/
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/benjojo/gophervista
2 |
3 | go 1.16
4 |
5 | require github.com/mattn/go-sqlite3 v1.14.10
6 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
2 | github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
3 |
--------------------------------------------------------------------------------
/rfc1436/gopher.go:
--------------------------------------------------------------------------------
1 | package rfc1436
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "net"
7 | "time"
8 | )
9 |
10 | func Get(uri string) (out Document, info GopherConnectionInfo, err error) {
11 | bin, ci, err := GetBinary(uri)
12 | if err != nil {
13 | return out, GopherConnectionInfo{}, err
14 | }
15 |
16 | Doc, err := parseDocument(bin)
17 | if err != nil {
18 | return out, ci, err
19 | }
20 |
21 | return Doc, ci, err
22 | }
23 |
24 | func GetBinary(uri string) (out []byte, info GopherConnectionInfo, err error) {
25 | path, hostname, port, err := ParseURI(uri)
26 | if err != nil {
27 | return out, GopherConnectionInfo{}, err
28 | }
29 |
30 | return requestRaw(path, hostname, port)
31 | }
32 |
33 | func requestRaw(path, hostname string, port int) (out []byte, info GopherConnectionInfo, err error) {
34 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", hostname, port), time.Second*5)
35 |
36 | cinfo := GopherConnectionInfo{
37 | Path: path,
38 | Hostname: hostname,
39 | Port: port,
40 | }
41 |
42 | if err != nil {
43 | return out, cinfo, err
44 | }
45 | conn.SetReadDeadline(time.Now().Add(time.Second * 10))
46 |
47 | defer conn.Close()
48 |
49 | if path == "/" {
50 | path = ""
51 | }
52 |
53 | payload := fmt.Sprintf("%s\r\n", path)
54 | _, err = conn.Write([]byte(payload))
55 | if err != nil {
56 | return out, cinfo, err
57 | }
58 |
59 | out, err = ioutil.ReadAll(conn)
60 | return out, cinfo, err
61 | }
62 |
--------------------------------------------------------------------------------
/rfc1436/parse.go:
--------------------------------------------------------------------------------
1 | package rfc1436
2 |
3 | import (
4 | "strconv"
5 | "strings"
6 | )
7 |
8 | // Gopher Message type codes
9 | // See: https://www.ietf.org/rfc/rfc1436.txt
10 | const (
11 | TypeTextFile = "0"
12 | TypeMenuEntity = "1"
13 | TypeCSOProtocol = "2"
14 | TypeErr = "3"
15 | TypeMacintoshBinHex = "4"
16 | TypePCDOS = "5"
17 | Typeuuencoded = "6"
18 | TypeIndexServer = "7"
19 | TypeTelnetSession = "8"
20 | TypeBinaryFile = "9"
21 | TypeDuplicatedServer = "+"
22 | TypeGIF = "g"
23 | TypeImage = "I"
24 | TypeTN3270 = "T"
25 | TypeHTML = "h"
26 | TypeMessage = "i"
27 | TypeWAVSound = "s"
28 | )
29 |
30 | // Document repersents a Gopher document that has been
31 | // parsed and ready to be processed for either
32 | // reading or rendering
33 | type Document struct {
34 | Raw []byte
35 | Items []Item
36 | }
37 |
38 | type Item struct {
39 | Type string
40 | Content string
41 | Host string
42 | Port int
43 | Path string
44 | }
45 |
46 | func parseDocument(in []byte) (D Document, err error) {
47 | D.Raw = in
48 | D.Items = make([]Item, 0)
49 |
50 | lines := strings.Split(string(in), "\r\n")
51 | for _, line := range lines {
52 | if line == "." {
53 | break
54 | }
55 |
56 | if !strings.Contains(line, "\t") {
57 | continue
58 | }
59 |
60 | if len(line) < 5 {
61 | // too short to be a gopher listing
62 | continue
63 | }
64 |
65 | if !isValidGopherType(string(line[:1])) {
66 | // is unparsable
67 | continue
68 | }
69 |
70 | e := Item{}
71 | e.Type = string(line[:1])
72 | parts := strings.Split(line[1:], "\t")
73 | if len(parts) != 4 {
74 | // Unexpected amounts of tabs
75 | continue
76 | }
77 |
78 | e.Content = parts[0]
79 | if !strings.HasPrefix(parts[1], "/") {
80 | parts[1] = "/" + parts[1]
81 | }
82 | e.Path = parts[1]
83 | e.Host = parts[2]
84 | pn, err := strconv.ParseInt(parts[3], 10, 16)
85 | if err != nil {
86 | // invalid port number
87 | continue
88 | }
89 | e.Port = int(pn)
90 |
91 | D.Items = append(D.Items, e)
92 | }
93 | return D, nil
94 | }
95 |
96 | func isValidGopherType(in string) bool {
97 | if in == "0" || in == "1" || in == "2" || in == "3" ||
98 | in == "4" || in == "5" || in == "6" || in == "7" ||
99 | in == "8" || in == "9" || in == "+" || in == "g" ||
100 | in == "I" || in == "T" || in == "h" || in == "i" ||
101 | in == "s" {
102 | return true
103 | }
104 | return false
105 | }
106 |
--------------------------------------------------------------------------------
/rfc1436/uri.go:
--------------------------------------------------------------------------------
1 | package rfc1436
2 |
3 | import (
4 | "fmt"
5 | "net/url"
6 | "strconv"
7 | "strings"
8 | )
9 |
10 | type GopherConnectionInfo struct {
11 | Path string
12 | Hostname string
13 | Port int
14 | }
15 |
16 | func ParseURI(inputURI string) (path, hostname string, port int, err error) {
17 | if strings.HasPrefix(inputURI, "gopher://") {
18 | U, err := url.Parse(inputURI)
19 | if err != nil {
20 | return "", "", 0, err
21 | }
22 |
23 | // Now figure the port out
24 | if strings.Contains(U.Host, ":") {
25 | parts := strings.Split(U.Host, ":")
26 | if len(parts) != 2 {
27 | return "", "", 0, fmt.Errorf("the URI provided has more than one colon")
28 | }
29 |
30 | p, err := strconv.ParseUint(parts[1], 10, 16)
31 | if err != nil {
32 | return "", "", 0, fmt.Errorf("port on URI is invalid")
33 | }
34 | return U.Path, parts[0], int(p), nil
35 | }
36 | return U.Path, U.Host, 70, nil
37 | }
38 | return ParseURI("gopher://" + inputURI)
39 | }
40 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/.codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | status:
3 | project: off
4 | patch: off
5 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/.gitignore:
--------------------------------------------------------------------------------
1 | *.db
2 | *.exe
3 | *.dll
4 | *.o
5 |
6 | # VSCode
7 | .vscode
8 |
9 | # Exclude from upgrade
10 | upgrade/*.c
11 | upgrade/*.h
12 |
13 | # Exclude upgrade binary
14 | upgrade/upgrade
15 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Yasuhiro Matsumoto
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/README.md:
--------------------------------------------------------------------------------
1 | go-sqlite3
2 | ==========
3 |
4 | [](http://godoc.org/github.com/mattn/go-sqlite3)
5 | [](https://github.com/mattn/go-sqlite3/actions?query=workflow%3AGo)
6 | [](https://opencollective.com/mattn-go-sqlite3)
7 | [](https://codecov.io/gh/mattn/go-sqlite3)
8 | [](https://goreportcard.com/report/github.com/mattn/go-sqlite3)
9 |
10 | Latest stable version is v1.14 or later, not v2.
11 |
12 | ~~**NOTE:** The increase to v2 was an accident. There were no major changes or features.~~
13 |
14 | # Description
15 |
16 | A sqlite3 driver that conforms to the built-in database/sql interface.
17 |
18 | Supported Golang version: See [.github/workflows/go.yaml](./.github/workflows/go.yaml).
19 |
20 | This package follows the official [Golang Release Policy](https://golang.org/doc/devel/release.html#policy).
21 |
22 | ### Overview
23 |
24 | - [go-sqlite3](#go-sqlite3)
25 | - [Description](#description)
26 | - [Overview](#overview)
27 | - [Installation](#installation)
28 | - [API Reference](#api-reference)
29 | - [Connection String](#connection-string)
30 | - [DSN Examples](#dsn-examples)
31 | - [Features](#features)
32 | - [Usage](#usage)
33 | - [Feature / Extension List](#feature--extension-list)
34 | - [Compilation](#compilation)
35 | - [Android](#android)
36 | - [ARM](#arm)
37 | - [Cross Compile](#cross-compile)
38 | - [Google Cloud Platform](#google-cloud-platform)
39 | - [Linux](#linux)
40 | - [Alpine](#alpine)
41 | - [Fedora](#fedora)
42 | - [Ubuntu](#ubuntu)
43 | - [Mac OSX](#mac-osx)
44 | - [Windows](#windows)
45 | - [Errors](#errors)
46 | - [User Authentication](#user-authentication)
47 | - [Compile](#compile)
48 | - [Usage](#usage-1)
49 | - [Create protected database](#create-protected-database)
50 | - [Password Encoding](#password-encoding)
51 | - [Available Encoders](#available-encoders)
52 | - [Restrictions](#restrictions)
53 | - [Support](#support)
54 | - [User Management](#user-management)
55 | - [SQL](#sql)
56 | - [Examples](#examples)
57 | - [*SQLiteConn](#sqliteconn)
58 | - [Attached database](#attached-database)
59 | - [Extensions](#extensions)
60 | - [Spatialite](#spatialite)
61 | - [FAQ](#faq)
62 | - [License](#license)
63 | - [Author](#author)
64 |
65 | # Installation
66 |
67 | This package can be installed with the `go get` command:
68 |
69 | go get github.com/mattn/go-sqlite3
70 |
71 | _go-sqlite3_ is *cgo* package.
72 | If you want to build your app using go-sqlite3, you need gcc.
73 | However, after you have built and installed _go-sqlite3_ with `go install github.com/mattn/go-sqlite3` (which requires gcc), you can build your app without relying on gcc in future.
74 |
75 | ***Important: because this is a `CGO` enabled package, you are required to set the environment variable `CGO_ENABLED=1` and have a `gcc` compile present within your path.***
76 |
77 | # API Reference
78 |
79 | API documentation can be found [here](http://godoc.org/github.com/mattn/go-sqlite3).
80 |
81 | Examples can be found under the [examples](./_example) directory.
82 |
83 | # Connection String
84 |
85 | When creating a new SQLite database or connection to an existing one, with the file name additional options can be given.
86 | This is also known as a DSN (Data Source Name) string.
87 |
88 | Options are append after the filename of the SQLite database.
89 | The database filename and options are separated by an `?` (Question Mark).
90 | Options should be URL-encoded (see [url.QueryEscape](https://golang.org/pkg/net/url/#QueryEscape)).
91 |
92 | This also applies when using an in-memory database instead of a file.
93 |
94 | Options can be given using the following format: `KEYWORD=VALUE` and multiple options can be combined with the `&` ampersand.
95 |
96 | This library supports DSN options of SQLite itself and provides additional options.
97 |
98 | Boolean values can be one of:
99 | * `0` `no` `false` `off`
100 | * `1` `yes` `true` `on`
101 |
102 | | Name | Key | Value(s) | Description |
103 | |------|-----|----------|-------------|
104 | | UA - Create | `_auth` | - | Create User Authentication, for more information see [User Authentication](#user-authentication) |
105 | | UA - Username | `_auth_user` | `string` | Username for User Authentication, for more information see [User Authentication](#user-authentication) |
106 | | UA - Password | `_auth_pass` | `string` | Password for User Authentication, for more information see [User Authentication](#user-authentication) |
107 | | UA - Crypt | `_auth_crypt` |
SHA1
SSHA1
SHA256
SSHA256
SHA384
SSHA384
SHA512
SSHA512
| Password encoder to use for User Authentication, for more information see [User Authentication](#user-authentication) |
108 | | UA - Salt | `_auth_salt` | `string` | Salt to use if the configure password encoder requires a salt, for User Authentication, for more information see [User Authentication](#user-authentication) |
109 | | Auto Vacuum | `_auto_vacuum` \| `_vacuum` |
`0` \| `none`
`1` \| `full`
`2` \| `incremental`
| For more information see [PRAGMA auto_vacuum](https://www.sqlite.org/pragma.html#pragma_auto_vacuum) |
110 | | Busy Timeout | `_busy_timeout` \| `_timeout` | `int` | Specify value for sqlite3_busy_timeout. For more information see [PRAGMA busy_timeout](https://www.sqlite.org/pragma.html#pragma_busy_timeout) |
111 | | Case Sensitive LIKE | `_case_sensitive_like` \| `_cslike` | `boolean` | For more information see [PRAGMA case_sensitive_like](https://www.sqlite.org/pragma.html#pragma_case_sensitive_like) |
112 | | Defer Foreign Keys | `_defer_foreign_keys` \| `_defer_fk` | `boolean` | For more information see [PRAGMA defer_foreign_keys](https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys) |
113 | | Foreign Keys | `_foreign_keys` \| `_fk` | `boolean` | For more information see [PRAGMA foreign_keys](https://www.sqlite.org/pragma.html#pragma_foreign_keys) |
114 | | Ignore CHECK Constraints | `_ignore_check_constraints` | `boolean` | For more information see [PRAGMA ignore_check_constraints](https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints) |
115 | | Immutable | `immutable` | `boolean` | For more information see [Immutable](https://www.sqlite.org/c3ref/open.html) |
116 | | Journal Mode | `_journal_mode` \| `_journal` |
DELETE
TRUNCATE
PERSIST
MEMORY
WAL
OFF
| For more information see [PRAGMA journal_mode](https://www.sqlite.org/pragma.html#pragma_journal_mode) |
117 | | Locking Mode | `_locking_mode` \| `_locking` |
NORMAL
EXCLUSIVE
| For more information see [PRAGMA locking_mode](https://www.sqlite.org/pragma.html#pragma_locking_mode) |
118 | | Mode | `mode` |
ro
rw
rwc
memory
| Access Mode of the database. For more information see [SQLite Open](https://www.sqlite.org/c3ref/open.html) |
119 | | Mutex Locking | `_mutex` |
no
full
| Specify mutex mode. |
120 | | Query Only | `_query_only` | `boolean` | For more information see [PRAGMA query_only](https://www.sqlite.org/pragma.html#pragma_query_only) |
121 | | Recursive Triggers | `_recursive_triggers` \| `_rt` | `boolean` | For more information see [PRAGMA recursive_triggers](https://www.sqlite.org/pragma.html#pragma_recursive_triggers) |
122 | | Secure Delete | `_secure_delete` | `boolean` \| `FAST` | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) |
123 | | Shared-Cache Mode | `cache` |
shared
private
| Set cache mode for more information see [sqlite.org](https://www.sqlite.org/sharedcache.html) |
124 | | Synchronous | `_synchronous` \| `_sync` |
0 \| OFF
1 \| NORMAL
2 \| FULL
3 \| EXTRA
| For more information see [PRAGMA synchronous](https://www.sqlite.org/pragma.html#pragma_synchronous) |
125 | | Time Zone Location | `_loc` | auto | Specify location of time format. |
126 | | Transaction Lock | `_txlock` |
immediate
deferred
exclusive
| Specify locking behavior for transactions. |
127 | | Writable Schema | `_writable_schema` | `Boolean` | When this pragma is on, the SQLITE_MASTER tables in which database can be changed using ordinary UPDATE, INSERT, and DELETE statements. Warning: misuse of this pragma can easily result in a corrupt database file. |
128 | | Cache Size | `_cache_size` | `int` | Maximum cache size; default is 2000K (2M). See [PRAGMA cache_size](https://sqlite.org/pragma.html#pragma_cache_size) |
129 |
130 |
131 | ## DSN Examples
132 |
133 | ```
134 | file:test.db?cache=shared&mode=memory
135 | ```
136 |
137 | # Features
138 |
139 | This package allows additional configuration of features available within SQLite3 to be enabled or disabled by golang build constraints also known as build `tags`.
140 |
141 | Click [here](https://golang.org/pkg/go/build/#hdr-Build_Constraints) for more information about build tags / constraints.
142 |
143 | ### Usage
144 |
145 | If you wish to build this library with additional extensions / features, use the following command:
146 |
147 | ```bash
148 | go build --tags ""
149 | ```
150 |
151 | For available features, see the extension list.
152 | When using multiple build tags, all the different tags should be space delimited.
153 |
154 | Example:
155 |
156 | ```bash
157 | go build --tags "icu json1 fts5 secure_delete"
158 | ```
159 |
160 | ### Feature / Extension List
161 |
162 | | Extension | Build Tag | Description |
163 | |-----------|-----------|-------------|
164 | | Additional Statistics | sqlite_stat4 | This option adds additional logic to the ANALYZE command and to the query planner that can help SQLite to chose a better query plan under certain situations. The ANALYZE command is enhanced to collect histogram data from all columns of every index and store that data in the sqlite_stat4 table.
The query planner will then use the histogram data to help it make better index choices. The downside of this compile-time option is that it violates the query planner stability guarantee making it more difficult to ensure consistent performance in mass-produced applications.
SQLITE_ENABLE_STAT4 is an enhancement of SQLITE_ENABLE_STAT3. STAT3 only recorded histogram data for the left-most column of each index whereas the STAT4 enhancement records histogram data from all columns of each index.
The SQLITE_ENABLE_STAT3 compile-time option is a no-op and is ignored if the SQLITE_ENABLE_STAT4 compile-time option is used |
165 | | Allow URI Authority | sqlite_allow_uri_authority | URI filenames normally throws an error if the authority section is not either empty or "localhost".
However, if SQLite is compiled with the SQLITE_ALLOW_URI_AUTHORITY compile-time option, then the URI is converted into a Uniform Naming Convention (UNC) filename and passed down to the underlying operating system that way |
166 | | App Armor | sqlite_app_armor | When defined, this C-preprocessor macro activates extra code that attempts to detect misuse of the SQLite API, such as passing in NULL pointers to required parameters or using objects after they have been destroyed.
App Armor is not available under `Windows`. |
167 | | Disable Load Extensions | sqlite_omit_load_extension | Loading of external extensions is enabled by default.
To disable extension loading add the build tag `sqlite_omit_load_extension`. |
168 | | Foreign Keys | sqlite_foreign_keys | This macro determines whether enforcement of foreign key constraints is enabled or disabled by default for new database connections.
Each database connection can always turn enforcement of foreign key constraints on and off and run-time using the foreign_keys pragma.
Enforcement of foreign key constraints is normally off by default, but if this compile-time parameter is set to 1, enforcement of foreign key constraints will be on by default |
169 | | Full Auto Vacuum | sqlite_vacuum_full | Set the default auto vacuum to full |
170 | | Incremental Auto Vacuum | sqlite_vacuum_incr | Set the default auto vacuum to incremental |
171 | | Full Text Search Engine | sqlite_fts5 | When this option is defined in the amalgamation, versions 5 of the full-text search engine (fts5) is added to the build automatically |
172 | | International Components for Unicode | sqlite_icu | This option causes the International Components for Unicode or "ICU" extension to SQLite to be added to the build |
173 | | Introspect PRAGMAS | sqlite_introspect | This option adds some extra PRAGMA statements.
PRAGMA function_list
PRAGMA module_list
PRAGMA pragma_list
|
174 | | JSON SQL Functions | sqlite_json | When this option is defined in the amalgamation, the JSON SQL functions are added to the build automatically |
175 | | Pre Update Hook | sqlite_preupdate_hook | Registers a callback function that is invoked prior to each INSERT, UPDATE, and DELETE operation on a database table. |
176 | | Secure Delete | sqlite_secure_delete | This compile-time option changes the default setting of the secure_delete pragma.
When this option is not used, secure_delete defaults to off. When this option is present, secure_delete defaults to on.
The secure_delete setting causes deleted content to be overwritten with zeros. There is a small performance penalty since additional I/O must occur.
On the other hand, secure_delete can prevent fragments of sensitive information from lingering in unused parts of the database file after it has been deleted. See the documentation on the secure_delete pragma for additional information |
177 | | Secure Delete (FAST) | sqlite_secure_delete_fast | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) |
178 | | Tracing / Debug | sqlite_trace | Activate trace functions |
179 | | User Authentication | sqlite_userauth | SQLite User Authentication see [User Authentication](#user-authentication) for more information. |
180 |
181 | # Compilation
182 |
183 | This package requires the `CGO_ENABLED=1` ennvironment variable if not set by default, and the presence of the `gcc` compiler.
184 |
185 | If you need to add additional CFLAGS or LDFLAGS to the build command, and do not want to modify this package, then this can be achieved by using the `CGO_CFLAGS` and `CGO_LDFLAGS` environment variables.
186 |
187 | ## Android
188 |
189 | This package can be compiled for android.
190 | Compile with:
191 |
192 | ```bash
193 | go build --tags "android"
194 | ```
195 |
196 | For more information see [#201](https://github.com/mattn/go-sqlite3/issues/201)
197 |
198 | # ARM
199 |
200 | To compile for `ARM` use the following environment:
201 |
202 | ```bash
203 | env CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ \
204 | CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 \
205 | go build -v
206 | ```
207 |
208 | Additional information:
209 | - [#242](https://github.com/mattn/go-sqlite3/issues/242)
210 | - [#504](https://github.com/mattn/go-sqlite3/issues/504)
211 |
212 | # Cross Compile
213 |
214 | This library can be cross-compiled.
215 |
216 | In some cases you are required to the `CC` environment variable with the cross compiler.
217 |
218 | ## Cross Compiling from MAC OSX
219 | The simplest way to cross compile from OSX is to use [xgo](https://github.com/karalabe/xgo).
220 |
221 | Steps:
222 | - Install [xgo](https://github.com/karalabe/xgo) (`go get github.com/karalabe/xgo`).
223 | - Ensure that your project is within your `GOPATH`.
224 | - Run `xgo local/path/to/project`.
225 |
226 | Please refer to the project's [README](https://github.com/karalabe/xgo/blob/master/README.md) for further information.
227 |
228 | # Google Cloud Platform
229 |
230 | Building on GCP is not possible because Google Cloud Platform does not allow `gcc` to be executed.
231 |
232 | Please work only with compiled final binaries.
233 |
234 | ## Linux
235 |
236 | To compile this package on Linux, you must install the development tools for your linux distribution.
237 |
238 | To compile under linux use the build tag `linux`.
239 |
240 | ```bash
241 | go build --tags "linux"
242 | ```
243 |
244 | If you wish to link directly to libsqlite3 then you can use the `libsqlite3` build tag.
245 |
246 | ```
247 | go build --tags "libsqlite3 linux"
248 | ```
249 |
250 | ### Alpine
251 |
252 | When building in an `alpine` container run the following command before building:
253 |
254 | ```
255 | apk add --update gcc musl-dev
256 | ```
257 |
258 | ### Fedora
259 |
260 | ```bash
261 | sudo yum groupinstall "Development Tools" "Development Libraries"
262 | ```
263 |
264 | ### Ubuntu
265 |
266 | ```bash
267 | sudo apt-get install build-essential
268 | ```
269 |
270 | ## Mac OSX
271 |
272 | OSX should have all the tools present to compile this package. If not, install XCode to add all the developers tools.
273 |
274 | Required dependency:
275 |
276 | ```bash
277 | brew install sqlite3
278 | ```
279 |
280 | For OSX, there is an additional package to install which is required if you wish to build the `icu` extension.
281 |
282 | This additional package can be installed with `homebrew`:
283 |
284 | ```bash
285 | brew upgrade icu4c
286 | ```
287 |
288 | To compile for Mac OSX:
289 |
290 | ```bash
291 | go build --tags "darwin"
292 | ```
293 |
294 | If you wish to link directly to libsqlite3, use the `libsqlite3` build tag:
295 |
296 | ```
297 | go build --tags "libsqlite3 darwin"
298 | ```
299 |
300 | Additional information:
301 | - [#206](https://github.com/mattn/go-sqlite3/issues/206)
302 | - [#404](https://github.com/mattn/go-sqlite3/issues/404)
303 |
304 | ## Windows
305 |
306 | To compile this package on Windows, you must have the `gcc` compiler installed.
307 |
308 | 1) Install a Windows `gcc` toolchain.
309 | 2) Add the `bin` folder to the Windows path, if the installer did not do this by default.
310 | 3) Open a terminal for the TDM-GCC toolchain, which can be found in the Windows Start menu.
311 | 4) Navigate to your project folder and run the `go build ...` command for this package.
312 |
313 | For example the TDM-GCC Toolchain can be found [here](https://jmeubank.github.io/tdm-gcc/).
314 |
315 | ## Errors
316 |
317 | - Compile error: `can not be used when making a shared object; recompile with -fPIC`
318 |
319 | When receiving a compile time error referencing recompile with `-FPIC` then you
320 | are probably using a hardend system.
321 |
322 | You can compile the library on a hardend system with the following command.
323 |
324 | ```bash
325 | go build -ldflags '-extldflags=-fno-PIC'
326 | ```
327 |
328 | More details see [#120](https://github.com/mattn/go-sqlite3/issues/120)
329 |
330 | - Can't build go-sqlite3 on windows 64bit.
331 |
332 | > Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit.
333 | > See: [#27](https://github.com/mattn/go-sqlite3/issues/27)
334 |
335 | - `go get github.com/mattn/go-sqlite3` throws compilation error.
336 |
337 | `gcc` throws: `internal compiler error`
338 |
339 | Remove the download repository from your disk and try re-install with:
340 |
341 | ```bash
342 | go install github.com/mattn/go-sqlite3
343 | ```
344 |
345 | # User Authentication
346 |
347 | This package supports the SQLite User Authentication module.
348 |
349 | ## Compile
350 |
351 | To use the User authentication module, the package has to be compiled with the tag `sqlite_userauth`. See [Features](#features).
352 |
353 | ## Usage
354 |
355 | ### Create protected database
356 |
357 | To create a database protected by user authentication, provide the following argument to the connection string `_auth`.
358 | This will enable user authentication within the database. This option however requires two additional arguments:
359 |
360 | - `_auth_user`
361 | - `_auth_pass`
362 |
363 | When `_auth` is present in the connection string user authentication will be enabled and the provided user will be created
364 | as an `admin` user. After initial creation, the parameter `_auth` has no effect anymore and can be omitted from the connection string.
365 |
366 | Example connection strings:
367 |
368 | Create an user authentication database with user `admin` and password `admin`:
369 |
370 | `file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin`
371 |
372 | Create an user authentication database with user `admin` and password `admin` and use `SHA1` for the password encoding:
373 |
374 | `file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin&_auth_crypt=sha1`
375 |
376 | ### Password Encoding
377 |
378 | The passwords within the user authentication module of SQLite are encoded with the SQLite function `sqlite_cryp`.
379 | This function uses a ceasar-cypher which is quite insecure.
380 | This library provides several additional password encoders which can be configured through the connection string.
381 |
382 | The password cypher can be configured with the key `_auth_crypt`. And if the configured password encoder also requires an
383 | salt this can be configured with `_auth_salt`.
384 |
385 | #### Available Encoders
386 |
387 | - SHA1
388 | - SSHA1 (Salted SHA1)
389 | - SHA256
390 | - SSHA256 (salted SHA256)
391 | - SHA384
392 | - SSHA384 (salted SHA384)
393 | - SHA512
394 | - SSHA512 (salted SHA512)
395 |
396 | ### Restrictions
397 |
398 | Operations on the database regarding user management can only be preformed by an administrator user.
399 |
400 | ### Support
401 |
402 | The user authentication supports two kinds of users:
403 |
404 | - administrators
405 | - regular users
406 |
407 | ### User Management
408 |
409 | User management can be done by directly using the `*SQLiteConn` or by SQL.
410 |
411 | #### SQL
412 |
413 | The following sql functions are available for user management:
414 |
415 | | Function | Arguments | Description |
416 | |----------|-----------|-------------|
417 | | `authenticate` | username `string`, password `string` | Will authenticate an user, this is done by the connection; and should not be used manually. |
418 | | `auth_user_add` | username `string`, password `string`, admin `int` | This function will add an user to the database. if the database is not protected by user authentication it will enable it. Argument `admin` is an integer identifying if the added user should be an administrator. Only Administrators can add administrators. |
419 | | `auth_user_change` | username `string`, password `string`, admin `int` | Function to modify an user. Users can change their own password, but only an administrator can change the administrator flag. |
420 | | `authUserDelete` | username `string` | Delete an user from the database. Can only be used by an administrator. The current logged in administrator cannot be deleted. This is to make sure their is always an administrator remaining. |
421 |
422 | These functions will return an integer:
423 |
424 | - 0 (SQLITE_OK)
425 | - 23 (SQLITE_AUTH) Failed to perform due to authentication or insufficient privileges
426 |
427 | ##### Examples
428 |
429 | ```sql
430 | // Autheticate user
431 | // Create Admin User
432 | SELECT auth_user_add('admin2', 'admin2', 1);
433 |
434 | // Change password for user
435 | SELECT auth_user_change('user', 'userpassword', 0);
436 |
437 | // Delete user
438 | SELECT user_delete('user');
439 | ```
440 |
441 | #### *SQLiteConn
442 |
443 | The following functions are available for User authentication from the `*SQLiteConn`:
444 |
445 | | Function | Description |
446 | |----------|-------------|
447 | | `Authenticate(username, password string) error` | Authenticate user |
448 | | `AuthUserAdd(username, password string, admin bool) error` | Add user |
449 | | `AuthUserChange(username, password string, admin bool) error` | Modify user |
450 | | `AuthUserDelete(username string) error` | Delete user |
451 |
452 | ### Attached database
453 |
454 | When using attached databases, SQLite will use the authentication from the `main` database for the attached database(s).
455 |
456 | # Extensions
457 |
458 | If you want your own extension to be listed here, or you want to add a reference to an extension; please submit an Issue for this.
459 |
460 | ## Spatialite
461 |
462 | Spatialite is available as an extension to SQLite, and can be used in combination with this repository.
463 | For an example, see [shaxbee/go-spatialite](https://github.com/shaxbee/go-spatialite).
464 |
465 | ## extension-functions.c from SQLite3 Contrib
466 |
467 | extension-functions.c is available as an extension to SQLite, and provides the following functions:
468 |
469 | - Math: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, difference, degrees, radians, cos, sin, tan, cot, cosh, sinh, tanh, coth, exp, log, log10, power, sign, sqrt, square, ceil, floor, pi.
470 | - String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim, replace, reverse, proper, padl, padr, padc, strfilter.
471 | - Aggregate: stdev, variance, mode, median, lower_quartile, upper_quartile
472 |
473 | For an example, see [dinedal/go-sqlite3-extension-functions](https://github.com/dinedal/go-sqlite3-extension-functions).
474 |
475 | # FAQ
476 |
477 | - Getting insert error while query is opened.
478 |
479 | > You can pass some arguments into the connection string, for example, a URI.
480 | > See: [#39](https://github.com/mattn/go-sqlite3/issues/39)
481 |
482 | - Do you want to cross compile? mingw on Linux or Mac?
483 |
484 | > See: [#106](https://github.com/mattn/go-sqlite3/issues/106)
485 | > See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html
486 |
487 | - Want to get time.Time with current locale
488 |
489 | Use `_loc=auto` in SQLite3 filename schema like `file:foo.db?_loc=auto`.
490 |
491 | - Can I use this in multiple routines concurrently?
492 |
493 | Yes for readonly. But not for writable. See [#50](https://github.com/mattn/go-sqlite3/issues/50), [#51](https://github.com/mattn/go-sqlite3/issues/51), [#209](https://github.com/mattn/go-sqlite3/issues/209), [#274](https://github.com/mattn/go-sqlite3/issues/274).
494 |
495 | - Why I'm getting `no such table` error?
496 |
497 | Why is it racy if I use a `sql.Open("sqlite3", ":memory:")` database?
498 |
499 | Each connection to `":memory:"` opens a brand new in-memory sql database, so if
500 | the stdlib's sql engine happens to open another connection and you've only
501 | specified `":memory:"`, that connection will see a brand new database. A
502 | workaround is to use `"file::memory:?cache=shared"` (or `"file:foobar?mode=memory&cache=shared"`). Every
503 | connection to this string will point to the same in-memory database.
504 |
505 | Note that if the last database connection in the pool closes, the in-memory database is deleted. Make sure the [max idle connection limit](https://golang.org/pkg/database/sql/#DB.SetMaxIdleConns) is > 0, and the [connection lifetime](https://golang.org/pkg/database/sql/#DB.SetConnMaxLifetime) is infinite.
506 |
507 | For more information see:
508 | * [#204](https://github.com/mattn/go-sqlite3/issues/204)
509 | * [#511](https://github.com/mattn/go-sqlite3/issues/511)
510 | * https://www.sqlite.org/sharedcache.html#shared_cache_and_in_memory_databases
511 | * https://www.sqlite.org/inmemorydb.html#sharedmemdb
512 |
513 | - Reading from database with large amount of goroutines fails on OSX.
514 |
515 | OS X limits OS-wide to not have more than 1000 files open simultaneously by default.
516 |
517 | For more information, see [#289](https://github.com/mattn/go-sqlite3/issues/289)
518 |
519 | - Trying to execute a `.` (dot) command throws an error.
520 |
521 | Error: `Error: near ".": syntax error`
522 | Dot command are part of SQLite3 CLI, not of this library.
523 |
524 | You need to implement the feature or call the sqlite3 cli.
525 |
526 | More information see [#305](https://github.com/mattn/go-sqlite3/issues/305).
527 |
528 | - Error: `database is locked`
529 |
530 | When you get a database is locked, please use the following options.
531 |
532 | Add to DSN: `cache=shared`
533 |
534 | Example:
535 | ```go
536 | db, err := sql.Open("sqlite3", "file:locked.sqlite?cache=shared")
537 | ```
538 |
539 | Next, please set the database connections of the SQL package to 1:
540 |
541 | ```go
542 | db.SetMaxOpenConns(1)
543 | ```
544 |
545 | For more information, see [#209](https://github.com/mattn/go-sqlite3/issues/209).
546 |
547 | ## Contributors
548 |
549 | ### Code Contributors
550 |
551 | This project exists thanks to all the people who [[contribute](CONTRIBUTING.md)].
552 |
553 |
554 | ### Financial Contributors
555 |
556 | Become a financial contributor and help us sustain our community. [[Contribute here](https://opencollective.com/mattn-go-sqlite3/contribute)].
557 |
558 | #### Individuals
559 |
560 |
561 |
562 | #### Organizations
563 |
564 | Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/mattn-go-sqlite3/contribute)]
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 | # License
578 |
579 | MIT: http://mattn.mit-license.org/2018
580 |
581 | sqlite3-binding.c, sqlite3-binding.h, sqlite3ext.h
582 |
583 | The -binding suffix was added to avoid build failures under gccgo.
584 |
585 | In this repository, those files are an amalgamation of code that was copied from SQLite3. The license of that code is the same as the license of SQLite3.
586 |
587 | # Author
588 |
589 | Yasuhiro Matsumoto (a.k.a mattn)
590 |
591 | G.J.R. Timmer
592 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/backup.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | package sqlite3
7 |
8 | /*
9 | #ifndef USE_LIBSQLITE3
10 | #include "sqlite3-binding.h"
11 | #else
12 | #include
13 | #endif
14 | #include
15 | */
16 | import "C"
17 | import (
18 | "runtime"
19 | "unsafe"
20 | )
21 |
22 | // SQLiteBackup implement interface of Backup.
23 | type SQLiteBackup struct {
24 | b *C.sqlite3_backup
25 | }
26 |
27 | // Backup make backup from src to dest.
28 | func (destConn *SQLiteConn) Backup(dest string, srcConn *SQLiteConn, src string) (*SQLiteBackup, error) {
29 | destptr := C.CString(dest)
30 | defer C.free(unsafe.Pointer(destptr))
31 | srcptr := C.CString(src)
32 | defer C.free(unsafe.Pointer(srcptr))
33 |
34 | if b := C.sqlite3_backup_init(destConn.db, destptr, srcConn.db, srcptr); b != nil {
35 | bb := &SQLiteBackup{b: b}
36 | runtime.SetFinalizer(bb, (*SQLiteBackup).Finish)
37 | return bb, nil
38 | }
39 | return nil, destConn.lastError()
40 | }
41 |
42 | // Step to backs up for one step. Calls the underlying `sqlite3_backup_step`
43 | // function. This function returns a boolean indicating if the backup is done
44 | // and an error signalling any other error. Done is returned if the underlying
45 | // C function returns SQLITE_DONE (Code 101)
46 | func (b *SQLiteBackup) Step(p int) (bool, error) {
47 | ret := C.sqlite3_backup_step(b.b, C.int(p))
48 | if ret == C.SQLITE_DONE {
49 | return true, nil
50 | } else if ret != 0 && ret != C.SQLITE_LOCKED && ret != C.SQLITE_BUSY {
51 | return false, Error{Code: ErrNo(ret)}
52 | }
53 | return false, nil
54 | }
55 |
56 | // Remaining return whether have the rest for backup.
57 | func (b *SQLiteBackup) Remaining() int {
58 | return int(C.sqlite3_backup_remaining(b.b))
59 | }
60 |
61 | // PageCount return count of pages.
62 | func (b *SQLiteBackup) PageCount() int {
63 | return int(C.sqlite3_backup_pagecount(b.b))
64 | }
65 |
66 | // Finish close backup.
67 | func (b *SQLiteBackup) Finish() error {
68 | return b.Close()
69 | }
70 |
71 | // Close close backup.
72 | func (b *SQLiteBackup) Close() error {
73 | ret := C.sqlite3_backup_finish(b.b)
74 |
75 | // sqlite3_backup_finish() never fails, it just returns the
76 | // error code from previous operations, so clean up before
77 | // checking and returning an error
78 | b.b = nil
79 | runtime.SetFinalizer(b, nil)
80 |
81 | if ret != 0 {
82 | return Error{Code: ErrNo(ret)}
83 | }
84 | return nil
85 | }
86 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/callback.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | package sqlite3
7 |
8 | // You can't export a Go function to C and have definitions in the C
9 | // preamble in the same file, so we have to have callbackTrampoline in
10 | // its own file. Because we need a separate file anyway, the support
11 | // code for SQLite custom functions is in here.
12 |
13 | /*
14 | #ifndef USE_LIBSQLITE3
15 | #include "sqlite3-binding.h"
16 | #else
17 | #include
18 | #endif
19 | #include
20 |
21 | void _sqlite3_result_text(sqlite3_context* ctx, const char* s);
22 | void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l);
23 | */
24 | import "C"
25 |
26 | import (
27 | "errors"
28 | "fmt"
29 | "math"
30 | "reflect"
31 | "sync"
32 | "unsafe"
33 | )
34 |
35 | //export callbackTrampoline
36 | func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
37 | args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
38 | fi := lookupHandle(C.sqlite3_user_data(ctx)).(*functionInfo)
39 | fi.Call(ctx, args)
40 | }
41 |
42 | //export stepTrampoline
43 | func stepTrampoline(ctx *C.sqlite3_context, argc C.int, argv **C.sqlite3_value) {
44 | args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:int(argc):int(argc)]
45 | ai := lookupHandle(C.sqlite3_user_data(ctx)).(*aggInfo)
46 | ai.Step(ctx, args)
47 | }
48 |
49 | //export doneTrampoline
50 | func doneTrampoline(ctx *C.sqlite3_context) {
51 | ai := lookupHandle(C.sqlite3_user_data(ctx)).(*aggInfo)
52 | ai.Done(ctx)
53 | }
54 |
55 | //export compareTrampoline
56 | func compareTrampoline(handlePtr unsafe.Pointer, la C.int, a *C.char, lb C.int, b *C.char) C.int {
57 | cmp := lookupHandle(handlePtr).(func(string, string) int)
58 | return C.int(cmp(C.GoStringN(a, la), C.GoStringN(b, lb)))
59 | }
60 |
61 | //export commitHookTrampoline
62 | func commitHookTrampoline(handle unsafe.Pointer) int {
63 | callback := lookupHandle(handle).(func() int)
64 | return callback()
65 | }
66 |
67 | //export rollbackHookTrampoline
68 | func rollbackHookTrampoline(handle unsafe.Pointer) {
69 | callback := lookupHandle(handle).(func())
70 | callback()
71 | }
72 |
73 | //export updateHookTrampoline
74 | func updateHookTrampoline(handle unsafe.Pointer, op int, db *C.char, table *C.char, rowid int64) {
75 | callback := lookupHandle(handle).(func(int, string, string, int64))
76 | callback(op, C.GoString(db), C.GoString(table), rowid)
77 | }
78 |
79 | //export authorizerTrampoline
80 | func authorizerTrampoline(handle unsafe.Pointer, op int, arg1 *C.char, arg2 *C.char, arg3 *C.char) int {
81 | callback := lookupHandle(handle).(func(int, string, string, string) int)
82 | return callback(op, C.GoString(arg1), C.GoString(arg2), C.GoString(arg3))
83 | }
84 |
85 | //export preUpdateHookTrampoline
86 | func preUpdateHookTrampoline(handle unsafe.Pointer, dbHandle uintptr, op int, db *C.char, table *C.char, oldrowid int64, newrowid int64) {
87 | hval := lookupHandleVal(handle)
88 | data := SQLitePreUpdateData{
89 | Conn: hval.db,
90 | Op: op,
91 | DatabaseName: C.GoString(db),
92 | TableName: C.GoString(table),
93 | OldRowID: oldrowid,
94 | NewRowID: newrowid,
95 | }
96 | callback := hval.val.(func(SQLitePreUpdateData))
97 | callback(data)
98 | }
99 |
100 | // Use handles to avoid passing Go pointers to C.
101 | type handleVal struct {
102 | db *SQLiteConn
103 | val interface{}
104 | }
105 |
106 | var handleLock sync.Mutex
107 | var handleVals = make(map[unsafe.Pointer]handleVal)
108 |
109 | func newHandle(db *SQLiteConn, v interface{}) unsafe.Pointer {
110 | handleLock.Lock()
111 | defer handleLock.Unlock()
112 | val := handleVal{db: db, val: v}
113 | var p unsafe.Pointer = C.malloc(C.size_t(1))
114 | if p == nil {
115 | panic("can't allocate 'cgo-pointer hack index pointer': ptr == nil")
116 | }
117 | handleVals[p] = val
118 | return p
119 | }
120 |
121 | func lookupHandleVal(handle unsafe.Pointer) handleVal {
122 | handleLock.Lock()
123 | defer handleLock.Unlock()
124 | return handleVals[handle]
125 | }
126 |
127 | func lookupHandle(handle unsafe.Pointer) interface{} {
128 | return lookupHandleVal(handle).val
129 | }
130 |
131 | func deleteHandles(db *SQLiteConn) {
132 | handleLock.Lock()
133 | defer handleLock.Unlock()
134 | for handle, val := range handleVals {
135 | if val.db == db {
136 | delete(handleVals, handle)
137 | C.free(handle)
138 | }
139 | }
140 | }
141 |
142 | // This is only here so that tests can refer to it.
143 | type callbackArgRaw C.sqlite3_value
144 |
145 | type callbackArgConverter func(*C.sqlite3_value) (reflect.Value, error)
146 |
147 | type callbackArgCast struct {
148 | f callbackArgConverter
149 | typ reflect.Type
150 | }
151 |
152 | func (c callbackArgCast) Run(v *C.sqlite3_value) (reflect.Value, error) {
153 | val, err := c.f(v)
154 | if err != nil {
155 | return reflect.Value{}, err
156 | }
157 | if !val.Type().ConvertibleTo(c.typ) {
158 | return reflect.Value{}, fmt.Errorf("cannot convert %s to %s", val.Type(), c.typ)
159 | }
160 | return val.Convert(c.typ), nil
161 | }
162 |
163 | func callbackArgInt64(v *C.sqlite3_value) (reflect.Value, error) {
164 | if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
165 | return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
166 | }
167 | return reflect.ValueOf(int64(C.sqlite3_value_int64(v))), nil
168 | }
169 |
170 | func callbackArgBool(v *C.sqlite3_value) (reflect.Value, error) {
171 | if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
172 | return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
173 | }
174 | i := int64(C.sqlite3_value_int64(v))
175 | val := false
176 | if i != 0 {
177 | val = true
178 | }
179 | return reflect.ValueOf(val), nil
180 | }
181 |
182 | func callbackArgFloat64(v *C.sqlite3_value) (reflect.Value, error) {
183 | if C.sqlite3_value_type(v) != C.SQLITE_FLOAT {
184 | return reflect.Value{}, fmt.Errorf("argument must be a FLOAT")
185 | }
186 | return reflect.ValueOf(float64(C.sqlite3_value_double(v))), nil
187 | }
188 |
189 | func callbackArgBytes(v *C.sqlite3_value) (reflect.Value, error) {
190 | switch C.sqlite3_value_type(v) {
191 | case C.SQLITE_BLOB:
192 | l := C.sqlite3_value_bytes(v)
193 | p := C.sqlite3_value_blob(v)
194 | return reflect.ValueOf(C.GoBytes(p, l)), nil
195 | case C.SQLITE_TEXT:
196 | l := C.sqlite3_value_bytes(v)
197 | c := unsafe.Pointer(C.sqlite3_value_text(v))
198 | return reflect.ValueOf(C.GoBytes(c, l)), nil
199 | default:
200 | return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
201 | }
202 | }
203 |
204 | func callbackArgString(v *C.sqlite3_value) (reflect.Value, error) {
205 | switch C.sqlite3_value_type(v) {
206 | case C.SQLITE_BLOB:
207 | l := C.sqlite3_value_bytes(v)
208 | p := (*C.char)(C.sqlite3_value_blob(v))
209 | return reflect.ValueOf(C.GoStringN(p, l)), nil
210 | case C.SQLITE_TEXT:
211 | c := (*C.char)(unsafe.Pointer(C.sqlite3_value_text(v)))
212 | return reflect.ValueOf(C.GoString(c)), nil
213 | default:
214 | return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
215 | }
216 | }
217 |
218 | func callbackArgGeneric(v *C.sqlite3_value) (reflect.Value, error) {
219 | switch C.sqlite3_value_type(v) {
220 | case C.SQLITE_INTEGER:
221 | return callbackArgInt64(v)
222 | case C.SQLITE_FLOAT:
223 | return callbackArgFloat64(v)
224 | case C.SQLITE_TEXT:
225 | return callbackArgString(v)
226 | case C.SQLITE_BLOB:
227 | return callbackArgBytes(v)
228 | case C.SQLITE_NULL:
229 | // Interpret NULL as a nil byte slice.
230 | var ret []byte
231 | return reflect.ValueOf(ret), nil
232 | default:
233 | panic("unreachable")
234 | }
235 | }
236 |
237 | func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
238 | switch typ.Kind() {
239 | case reflect.Interface:
240 | if typ.NumMethod() != 0 {
241 | return nil, errors.New("the only supported interface type is interface{}")
242 | }
243 | return callbackArgGeneric, nil
244 | case reflect.Slice:
245 | if typ.Elem().Kind() != reflect.Uint8 {
246 | return nil, errors.New("the only supported slice type is []byte")
247 | }
248 | return callbackArgBytes, nil
249 | case reflect.String:
250 | return callbackArgString, nil
251 | case reflect.Bool:
252 | return callbackArgBool, nil
253 | case reflect.Int64:
254 | return callbackArgInt64, nil
255 | case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
256 | c := callbackArgCast{callbackArgInt64, typ}
257 | return c.Run, nil
258 | case reflect.Float64:
259 | return callbackArgFloat64, nil
260 | case reflect.Float32:
261 | c := callbackArgCast{callbackArgFloat64, typ}
262 | return c.Run, nil
263 | default:
264 | return nil, fmt.Errorf("don't know how to convert to %s", typ)
265 | }
266 | }
267 |
268 | func callbackConvertArgs(argv []*C.sqlite3_value, converters []callbackArgConverter, variadic callbackArgConverter) ([]reflect.Value, error) {
269 | var args []reflect.Value
270 |
271 | if len(argv) < len(converters) {
272 | return nil, fmt.Errorf("function requires at least %d arguments", len(converters))
273 | }
274 |
275 | for i, arg := range argv[:len(converters)] {
276 | v, err := converters[i](arg)
277 | if err != nil {
278 | return nil, err
279 | }
280 | args = append(args, v)
281 | }
282 |
283 | if variadic != nil {
284 | for _, arg := range argv[len(converters):] {
285 | v, err := variadic(arg)
286 | if err != nil {
287 | return nil, err
288 | }
289 | args = append(args, v)
290 | }
291 | }
292 | return args, nil
293 | }
294 |
295 | type callbackRetConverter func(*C.sqlite3_context, reflect.Value) error
296 |
297 | func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
298 | switch v.Type().Kind() {
299 | case reflect.Int64:
300 | case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
301 | v = v.Convert(reflect.TypeOf(int64(0)))
302 | case reflect.Bool:
303 | b := v.Interface().(bool)
304 | if b {
305 | v = reflect.ValueOf(int64(1))
306 | } else {
307 | v = reflect.ValueOf(int64(0))
308 | }
309 | default:
310 | return fmt.Errorf("cannot convert %s to INTEGER", v.Type())
311 | }
312 |
313 | C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64)))
314 | return nil
315 | }
316 |
317 | func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error {
318 | switch v.Type().Kind() {
319 | case reflect.Float64:
320 | case reflect.Float32:
321 | v = v.Convert(reflect.TypeOf(float64(0)))
322 | default:
323 | return fmt.Errorf("cannot convert %s to FLOAT", v.Type())
324 | }
325 |
326 | C.sqlite3_result_double(ctx, C.double(v.Interface().(float64)))
327 | return nil
328 | }
329 |
330 | func callbackRetBlob(ctx *C.sqlite3_context, v reflect.Value) error {
331 | if v.Type().Kind() != reflect.Slice || v.Type().Elem().Kind() != reflect.Uint8 {
332 | return fmt.Errorf("cannot convert %s to BLOB", v.Type())
333 | }
334 | i := v.Interface()
335 | if i == nil || len(i.([]byte)) == 0 {
336 | C.sqlite3_result_null(ctx)
337 | } else {
338 | bs := i.([]byte)
339 | C._sqlite3_result_blob(ctx, unsafe.Pointer(&bs[0]), C.int(len(bs)))
340 | }
341 | return nil
342 | }
343 |
344 | func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error {
345 | if v.Type().Kind() != reflect.String {
346 | return fmt.Errorf("cannot convert %s to TEXT", v.Type())
347 | }
348 | C._sqlite3_result_text(ctx, C.CString(v.Interface().(string)))
349 | return nil
350 | }
351 |
352 | func callbackRetNil(ctx *C.sqlite3_context, v reflect.Value) error {
353 | return nil
354 | }
355 |
356 | func callbackRet(typ reflect.Type) (callbackRetConverter, error) {
357 | switch typ.Kind() {
358 | case reflect.Interface:
359 | errorInterface := reflect.TypeOf((*error)(nil)).Elem()
360 | if typ.Implements(errorInterface) {
361 | return callbackRetNil, nil
362 | }
363 | fallthrough
364 | case reflect.Slice:
365 | if typ.Elem().Kind() != reflect.Uint8 {
366 | return nil, errors.New("the only supported slice type is []byte")
367 | }
368 | return callbackRetBlob, nil
369 | case reflect.String:
370 | return callbackRetText, nil
371 | case reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
372 | return callbackRetInteger, nil
373 | case reflect.Float32, reflect.Float64:
374 | return callbackRetFloat, nil
375 | default:
376 | return nil, fmt.Errorf("don't know how to convert to %s", typ)
377 | }
378 | }
379 |
380 | func callbackError(ctx *C.sqlite3_context, err error) {
381 | cstr := C.CString(err.Error())
382 | defer C.free(unsafe.Pointer(cstr))
383 | C.sqlite3_result_error(ctx, cstr, C.int(-1))
384 | }
385 |
386 | // Test support code. Tests are not allowed to import "C", so we can't
387 | // declare any functions that use C.sqlite3_value.
388 | func callbackSyntheticForTests(v reflect.Value, err error) callbackArgConverter {
389 | return func(*C.sqlite3_value) (reflect.Value, error) {
390 | return v, err
391 | }
392 | }
393 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/convert.go:
--------------------------------------------------------------------------------
1 | // Extracted from Go database/sql source code
2 |
3 | // Copyright 2011 The Go Authors. All rights reserved.
4 | // Use of this source code is governed by a BSD-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // Type conversions for Scan.
8 |
9 | package sqlite3
10 |
11 | import (
12 | "database/sql"
13 | "database/sql/driver"
14 | "errors"
15 | "fmt"
16 | "reflect"
17 | "strconv"
18 | "time"
19 | )
20 |
21 | var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
22 |
23 | // convertAssign copies to dest the value in src, converting it if possible.
24 | // An error is returned if the copy would result in loss of information.
25 | // dest should be a pointer type.
26 | func convertAssign(dest, src interface{}) error {
27 | // Common cases, without reflect.
28 | switch s := src.(type) {
29 | case string:
30 | switch d := dest.(type) {
31 | case *string:
32 | if d == nil {
33 | return errNilPtr
34 | }
35 | *d = s
36 | return nil
37 | case *[]byte:
38 | if d == nil {
39 | return errNilPtr
40 | }
41 | *d = []byte(s)
42 | return nil
43 | case *sql.RawBytes:
44 | if d == nil {
45 | return errNilPtr
46 | }
47 | *d = append((*d)[:0], s...)
48 | return nil
49 | }
50 | case []byte:
51 | switch d := dest.(type) {
52 | case *string:
53 | if d == nil {
54 | return errNilPtr
55 | }
56 | *d = string(s)
57 | return nil
58 | case *interface{}:
59 | if d == nil {
60 | return errNilPtr
61 | }
62 | *d = cloneBytes(s)
63 | return nil
64 | case *[]byte:
65 | if d == nil {
66 | return errNilPtr
67 | }
68 | *d = cloneBytes(s)
69 | return nil
70 | case *sql.RawBytes:
71 | if d == nil {
72 | return errNilPtr
73 | }
74 | *d = s
75 | return nil
76 | }
77 | case time.Time:
78 | switch d := dest.(type) {
79 | case *time.Time:
80 | *d = s
81 | return nil
82 | case *string:
83 | *d = s.Format(time.RFC3339Nano)
84 | return nil
85 | case *[]byte:
86 | if d == nil {
87 | return errNilPtr
88 | }
89 | *d = []byte(s.Format(time.RFC3339Nano))
90 | return nil
91 | case *sql.RawBytes:
92 | if d == nil {
93 | return errNilPtr
94 | }
95 | *d = s.AppendFormat((*d)[:0], time.RFC3339Nano)
96 | return nil
97 | }
98 | case nil:
99 | switch d := dest.(type) {
100 | case *interface{}:
101 | if d == nil {
102 | return errNilPtr
103 | }
104 | *d = nil
105 | return nil
106 | case *[]byte:
107 | if d == nil {
108 | return errNilPtr
109 | }
110 | *d = nil
111 | return nil
112 | case *sql.RawBytes:
113 | if d == nil {
114 | return errNilPtr
115 | }
116 | *d = nil
117 | return nil
118 | }
119 | }
120 |
121 | var sv reflect.Value
122 |
123 | switch d := dest.(type) {
124 | case *string:
125 | sv = reflect.ValueOf(src)
126 | switch sv.Kind() {
127 | case reflect.Bool,
128 | reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
129 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
130 | reflect.Float32, reflect.Float64:
131 | *d = asString(src)
132 | return nil
133 | }
134 | case *[]byte:
135 | sv = reflect.ValueOf(src)
136 | if b, ok := asBytes(nil, sv); ok {
137 | *d = b
138 | return nil
139 | }
140 | case *sql.RawBytes:
141 | sv = reflect.ValueOf(src)
142 | if b, ok := asBytes([]byte(*d)[:0], sv); ok {
143 | *d = sql.RawBytes(b)
144 | return nil
145 | }
146 | case *bool:
147 | bv, err := driver.Bool.ConvertValue(src)
148 | if err == nil {
149 | *d = bv.(bool)
150 | }
151 | return err
152 | case *interface{}:
153 | *d = src
154 | return nil
155 | }
156 |
157 | if scanner, ok := dest.(sql.Scanner); ok {
158 | return scanner.Scan(src)
159 | }
160 |
161 | dpv := reflect.ValueOf(dest)
162 | if dpv.Kind() != reflect.Ptr {
163 | return errors.New("destination not a pointer")
164 | }
165 | if dpv.IsNil() {
166 | return errNilPtr
167 | }
168 |
169 | if !sv.IsValid() {
170 | sv = reflect.ValueOf(src)
171 | }
172 |
173 | dv := reflect.Indirect(dpv)
174 | if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
175 | switch b := src.(type) {
176 | case []byte:
177 | dv.Set(reflect.ValueOf(cloneBytes(b)))
178 | default:
179 | dv.Set(sv)
180 | }
181 | return nil
182 | }
183 |
184 | if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
185 | dv.Set(sv.Convert(dv.Type()))
186 | return nil
187 | }
188 |
189 | // The following conversions use a string value as an intermediate representation
190 | // to convert between various numeric types.
191 | //
192 | // This also allows scanning into user defined types such as "type Int int64".
193 | // For symmetry, also check for string destination types.
194 | switch dv.Kind() {
195 | case reflect.Ptr:
196 | if src == nil {
197 | dv.Set(reflect.Zero(dv.Type()))
198 | return nil
199 | }
200 | dv.Set(reflect.New(dv.Type().Elem()))
201 | return convertAssign(dv.Interface(), src)
202 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
203 | s := asString(src)
204 | i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
205 | if err != nil {
206 | err = strconvErr(err)
207 | return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
208 | }
209 | dv.SetInt(i64)
210 | return nil
211 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
212 | s := asString(src)
213 | u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
214 | if err != nil {
215 | err = strconvErr(err)
216 | return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
217 | }
218 | dv.SetUint(u64)
219 | return nil
220 | case reflect.Float32, reflect.Float64:
221 | s := asString(src)
222 | f64, err := strconv.ParseFloat(s, dv.Type().Bits())
223 | if err != nil {
224 | err = strconvErr(err)
225 | return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
226 | }
227 | dv.SetFloat(f64)
228 | return nil
229 | case reflect.String:
230 | switch v := src.(type) {
231 | case string:
232 | dv.SetString(v)
233 | return nil
234 | case []byte:
235 | dv.SetString(string(v))
236 | return nil
237 | }
238 | }
239 |
240 | return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
241 | }
242 |
243 | func strconvErr(err error) error {
244 | if ne, ok := err.(*strconv.NumError); ok {
245 | return ne.Err
246 | }
247 | return err
248 | }
249 |
250 | func cloneBytes(b []byte) []byte {
251 | if b == nil {
252 | return nil
253 | }
254 | c := make([]byte, len(b))
255 | copy(c, b)
256 | return c
257 | }
258 |
259 | func asString(src interface{}) string {
260 | switch v := src.(type) {
261 | case string:
262 | return v
263 | case []byte:
264 | return string(v)
265 | }
266 | rv := reflect.ValueOf(src)
267 | switch rv.Kind() {
268 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
269 | return strconv.FormatInt(rv.Int(), 10)
270 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
271 | return strconv.FormatUint(rv.Uint(), 10)
272 | case reflect.Float64:
273 | return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
274 | case reflect.Float32:
275 | return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
276 | case reflect.Bool:
277 | return strconv.FormatBool(rv.Bool())
278 | }
279 | return fmt.Sprintf("%v", src)
280 | }
281 |
282 | func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
283 | switch rv.Kind() {
284 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
285 | return strconv.AppendInt(buf, rv.Int(), 10), true
286 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
287 | return strconv.AppendUint(buf, rv.Uint(), 10), true
288 | case reflect.Float32:
289 | return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
290 | case reflect.Float64:
291 | return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
292 | case reflect.Bool:
293 | return strconv.AppendBool(buf, rv.Bool()), true
294 | case reflect.String:
295 | s := rv.String()
296 | return append(buf, s...), true
297 | }
298 | return
299 | }
300 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package sqlite3 provides interface to SQLite3 databases.
3 |
4 | This works as a driver for database/sql.
5 |
6 | Installation
7 |
8 | go get github.com/mattn/go-sqlite3
9 |
10 | Supported Types
11 |
12 | Currently, go-sqlite3 supports the following data types.
13 |
14 | +------------------------------+
15 | |go | sqlite3 |
16 | |----------|-------------------|
17 | |nil | null |
18 | |int | integer |
19 | |int64 | integer |
20 | |float64 | float |
21 | |bool | integer |
22 | |[]byte | blob |
23 | |string | text |
24 | |time.Time | timestamp/datetime|
25 | +------------------------------+
26 |
27 | SQLite3 Extension
28 |
29 | You can write your own extension module for sqlite3. For example, below is an
30 | extension for a Regexp matcher operation.
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | SQLITE_EXTENSION_INIT1
38 | static void regexp_func(sqlite3_context *context, int argc, sqlite3_value **argv) {
39 | if (argc >= 2) {
40 | const char *target = (const char *)sqlite3_value_text(argv[1]);
41 | const char *pattern = (const char *)sqlite3_value_text(argv[0]);
42 | const char* errstr = NULL;
43 | int erroff = 0;
44 | int vec[500];
45 | int n, rc;
46 | pcre* re = pcre_compile(pattern, 0, &errstr, &erroff, NULL);
47 | rc = pcre_exec(re, NULL, target, strlen(target), 0, 0, vec, 500);
48 | if (rc <= 0) {
49 | sqlite3_result_error(context, errstr, 0);
50 | return;
51 | }
52 | sqlite3_result_int(context, 1);
53 | }
54 | }
55 |
56 | #ifdef _WIN32
57 | __declspec(dllexport)
58 | #endif
59 | int sqlite3_extension_init(sqlite3 *db, char **errmsg,
60 | const sqlite3_api_routines *api) {
61 | SQLITE_EXTENSION_INIT2(api);
62 | return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8,
63 | (void*)db, regexp_func, NULL, NULL);
64 | }
65 |
66 | It needs to be built as a so/dll shared library. And you need to register
67 | the extension module like below.
68 |
69 | sql.Register("sqlite3_with_extensions",
70 | &sqlite3.SQLiteDriver{
71 | Extensions: []string{
72 | "sqlite3_mod_regexp",
73 | },
74 | })
75 |
76 | Then, you can use this extension.
77 |
78 | rows, err := db.Query("select text from mytable where name regexp '^golang'")
79 |
80 | Connection Hook
81 |
82 | You can hook and inject your code when the connection is established by setting
83 | ConnectHook to get the SQLiteConn.
84 |
85 | sql.Register("sqlite3_with_hook_example",
86 | &sqlite3.SQLiteDriver{
87 | ConnectHook: func(conn *sqlite3.SQLiteConn) error {
88 | sqlite3conn = append(sqlite3conn, conn)
89 | return nil
90 | },
91 | })
92 |
93 | You can also use database/sql.Conn.Raw (Go >= 1.13):
94 |
95 | conn, err := db.Conn(context.Background())
96 | // if err != nil { ... }
97 | defer conn.Close()
98 | err = conn.Raw(func (driverConn interface{}) error {
99 | sqliteConn := driverConn.(*sqlite3.SQLiteConn)
100 | // ... use sqliteConn
101 | })
102 | // if err != nil { ... }
103 |
104 | Go SQlite3 Extensions
105 |
106 | If you want to register Go functions as SQLite extension functions
107 | you can make a custom driver by calling RegisterFunction from
108 | ConnectHook.
109 |
110 | regex = func(re, s string) (bool, error) {
111 | return regexp.MatchString(re, s)
112 | }
113 | sql.Register("sqlite3_extended",
114 | &sqlite3.SQLiteDriver{
115 | ConnectHook: func(conn *sqlite3.SQLiteConn) error {
116 | return conn.RegisterFunc("regexp", regex, true)
117 | },
118 | })
119 |
120 | You can then use the custom driver by passing its name to sql.Open.
121 |
122 | var i int
123 | conn, err := sql.Open("sqlite3_extended", "./foo.db")
124 | if err != nil {
125 | panic(err)
126 | }
127 | err = db.QueryRow(`SELECT regexp("foo.*", "seafood")`).Scan(&i)
128 | if err != nil {
129 | panic(err)
130 | }
131 |
132 | See the documentation of RegisterFunc for more details.
133 |
134 | */
135 | package sqlite3
136 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/error.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | package sqlite3
7 |
8 | /*
9 | #ifndef USE_LIBSQLITE3
10 | #include "sqlite3-binding.h"
11 | #else
12 | #include
13 | #endif
14 | */
15 | import "C"
16 | import "syscall"
17 |
18 | // ErrNo inherit errno.
19 | type ErrNo int
20 |
21 | // ErrNoMask is mask code.
22 | const ErrNoMask C.int = 0xff
23 |
24 | // ErrNoExtended is extended errno.
25 | type ErrNoExtended int
26 |
27 | // Error implement sqlite error code.
28 | type Error struct {
29 | Code ErrNo /* The error code returned by SQLite */
30 | ExtendedCode ErrNoExtended /* The extended error code returned by SQLite */
31 | SystemErrno syscall.Errno /* The system errno returned by the OS through SQLite, if applicable */
32 | err string /* The error string returned by sqlite3_errmsg(),
33 | this usually contains more specific details. */
34 | }
35 |
36 | // result codes from http://www.sqlite.org/c3ref/c_abort.html
37 | var (
38 | ErrError = ErrNo(1) /* SQL error or missing database */
39 | ErrInternal = ErrNo(2) /* Internal logic error in SQLite */
40 | ErrPerm = ErrNo(3) /* Access permission denied */
41 | ErrAbort = ErrNo(4) /* Callback routine requested an abort */
42 | ErrBusy = ErrNo(5) /* The database file is locked */
43 | ErrLocked = ErrNo(6) /* A table in the database is locked */
44 | ErrNomem = ErrNo(7) /* A malloc() failed */
45 | ErrReadonly = ErrNo(8) /* Attempt to write a readonly database */
46 | ErrInterrupt = ErrNo(9) /* Operation terminated by sqlite3_interrupt() */
47 | ErrIoErr = ErrNo(10) /* Some kind of disk I/O error occurred */
48 | ErrCorrupt = ErrNo(11) /* The database disk image is malformed */
49 | ErrNotFound = ErrNo(12) /* Unknown opcode in sqlite3_file_control() */
50 | ErrFull = ErrNo(13) /* Insertion failed because database is full */
51 | ErrCantOpen = ErrNo(14) /* Unable to open the database file */
52 | ErrProtocol = ErrNo(15) /* Database lock protocol error */
53 | ErrEmpty = ErrNo(16) /* Database is empty */
54 | ErrSchema = ErrNo(17) /* The database schema changed */
55 | ErrTooBig = ErrNo(18) /* String or BLOB exceeds size limit */
56 | ErrConstraint = ErrNo(19) /* Abort due to constraint violation */
57 | ErrMismatch = ErrNo(20) /* Data type mismatch */
58 | ErrMisuse = ErrNo(21) /* Library used incorrectly */
59 | ErrNoLFS = ErrNo(22) /* Uses OS features not supported on host */
60 | ErrAuth = ErrNo(23) /* Authorization denied */
61 | ErrFormat = ErrNo(24) /* Auxiliary database format error */
62 | ErrRange = ErrNo(25) /* 2nd parameter to sqlite3_bind out of range */
63 | ErrNotADB = ErrNo(26) /* File opened that is not a database file */
64 | ErrNotice = ErrNo(27) /* Notifications from sqlite3_log() */
65 | ErrWarning = ErrNo(28) /* Warnings from sqlite3_log() */
66 | )
67 |
68 | // Error return error message from errno.
69 | func (err ErrNo) Error() string {
70 | return Error{Code: err}.Error()
71 | }
72 |
73 | // Extend return extended errno.
74 | func (err ErrNo) Extend(by int) ErrNoExtended {
75 | return ErrNoExtended(int(err) | (by << 8))
76 | }
77 |
78 | // Error return error message that is extended code.
79 | func (err ErrNoExtended) Error() string {
80 | return Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}.Error()
81 | }
82 |
83 | func (err Error) Error() string {
84 | var str string
85 | if err.err != "" {
86 | str = err.err
87 | } else {
88 | str = C.GoString(C.sqlite3_errstr(C.int(err.Code)))
89 | }
90 | if err.SystemErrno != 0 {
91 | str += ": " + err.SystemErrno.Error()
92 | }
93 | return str
94 | }
95 |
96 | // result codes from http://www.sqlite.org/c3ref/c_abort_rollback.html
97 | var (
98 | ErrIoErrRead = ErrIoErr.Extend(1)
99 | ErrIoErrShortRead = ErrIoErr.Extend(2)
100 | ErrIoErrWrite = ErrIoErr.Extend(3)
101 | ErrIoErrFsync = ErrIoErr.Extend(4)
102 | ErrIoErrDirFsync = ErrIoErr.Extend(5)
103 | ErrIoErrTruncate = ErrIoErr.Extend(6)
104 | ErrIoErrFstat = ErrIoErr.Extend(7)
105 | ErrIoErrUnlock = ErrIoErr.Extend(8)
106 | ErrIoErrRDlock = ErrIoErr.Extend(9)
107 | ErrIoErrDelete = ErrIoErr.Extend(10)
108 | ErrIoErrBlocked = ErrIoErr.Extend(11)
109 | ErrIoErrNoMem = ErrIoErr.Extend(12)
110 | ErrIoErrAccess = ErrIoErr.Extend(13)
111 | ErrIoErrCheckReservedLock = ErrIoErr.Extend(14)
112 | ErrIoErrLock = ErrIoErr.Extend(15)
113 | ErrIoErrClose = ErrIoErr.Extend(16)
114 | ErrIoErrDirClose = ErrIoErr.Extend(17)
115 | ErrIoErrSHMOpen = ErrIoErr.Extend(18)
116 | ErrIoErrSHMSize = ErrIoErr.Extend(19)
117 | ErrIoErrSHMLock = ErrIoErr.Extend(20)
118 | ErrIoErrSHMMap = ErrIoErr.Extend(21)
119 | ErrIoErrSeek = ErrIoErr.Extend(22)
120 | ErrIoErrDeleteNoent = ErrIoErr.Extend(23)
121 | ErrIoErrMMap = ErrIoErr.Extend(24)
122 | ErrIoErrGetTempPath = ErrIoErr.Extend(25)
123 | ErrIoErrConvPath = ErrIoErr.Extend(26)
124 | ErrLockedSharedCache = ErrLocked.Extend(1)
125 | ErrBusyRecovery = ErrBusy.Extend(1)
126 | ErrBusySnapshot = ErrBusy.Extend(2)
127 | ErrCantOpenNoTempDir = ErrCantOpen.Extend(1)
128 | ErrCantOpenIsDir = ErrCantOpen.Extend(2)
129 | ErrCantOpenFullPath = ErrCantOpen.Extend(3)
130 | ErrCantOpenConvPath = ErrCantOpen.Extend(4)
131 | ErrCorruptVTab = ErrCorrupt.Extend(1)
132 | ErrReadonlyRecovery = ErrReadonly.Extend(1)
133 | ErrReadonlyCantLock = ErrReadonly.Extend(2)
134 | ErrReadonlyRollback = ErrReadonly.Extend(3)
135 | ErrReadonlyDbMoved = ErrReadonly.Extend(4)
136 | ErrAbortRollback = ErrAbort.Extend(2)
137 | ErrConstraintCheck = ErrConstraint.Extend(1)
138 | ErrConstraintCommitHook = ErrConstraint.Extend(2)
139 | ErrConstraintForeignKey = ErrConstraint.Extend(3)
140 | ErrConstraintFunction = ErrConstraint.Extend(4)
141 | ErrConstraintNotNull = ErrConstraint.Extend(5)
142 | ErrConstraintPrimaryKey = ErrConstraint.Extend(6)
143 | ErrConstraintTrigger = ErrConstraint.Extend(7)
144 | ErrConstraintUnique = ErrConstraint.Extend(8)
145 | ErrConstraintVTab = ErrConstraint.Extend(9)
146 | ErrConstraintRowID = ErrConstraint.Extend(10)
147 | ErrNoticeRecoverWAL = ErrNotice.Extend(1)
148 | ErrNoticeRecoverRollback = ErrNotice.Extend(2)
149 | ErrWarningAutoIndex = ErrWarning.Extend(1)
150 | )
151 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/mattn/go-sqlite3
2 |
3 | go 1.12
4 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/go.sum:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjojo/gophervista/0778fcb538da8532fa01652dc290c551aa1543c6/vendor/github.com/mattn/go-sqlite3/go.sum
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_context.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | package sqlite3
7 |
8 | /*
9 |
10 | #ifndef USE_LIBSQLITE3
11 | #include "sqlite3-binding.h"
12 | #else
13 | #include
14 | #endif
15 | #include
16 | // These wrappers are necessary because SQLITE_TRANSIENT
17 | // is a pointer constant, and cgo doesn't translate them correctly.
18 |
19 | static inline void my_result_text(sqlite3_context *ctx, char *p, int np) {
20 | sqlite3_result_text(ctx, p, np, SQLITE_TRANSIENT);
21 | }
22 |
23 | static inline void my_result_blob(sqlite3_context *ctx, void *p, int np) {
24 | sqlite3_result_blob(ctx, p, np, SQLITE_TRANSIENT);
25 | }
26 | */
27 | import "C"
28 |
29 | import (
30 | "math"
31 | "reflect"
32 | "unsafe"
33 | )
34 |
35 | const i64 = unsafe.Sizeof(int(0)) > 4
36 |
37 | // SQLiteContext behave sqlite3_context
38 | type SQLiteContext C.sqlite3_context
39 |
40 | // ResultBool sets the result of an SQL function.
41 | func (c *SQLiteContext) ResultBool(b bool) {
42 | if b {
43 | c.ResultInt(1)
44 | } else {
45 | c.ResultInt(0)
46 | }
47 | }
48 |
49 | // ResultBlob sets the result of an SQL function.
50 | // See: sqlite3_result_blob, http://sqlite.org/c3ref/result_blob.html
51 | func (c *SQLiteContext) ResultBlob(b []byte) {
52 | if i64 && len(b) > math.MaxInt32 {
53 | C.sqlite3_result_error_toobig((*C.sqlite3_context)(c))
54 | return
55 | }
56 | var p *byte
57 | if len(b) > 0 {
58 | p = &b[0]
59 | }
60 | C.my_result_blob((*C.sqlite3_context)(c), unsafe.Pointer(p), C.int(len(b)))
61 | }
62 |
63 | // ResultDouble sets the result of an SQL function.
64 | // See: sqlite3_result_double, http://sqlite.org/c3ref/result_blob.html
65 | func (c *SQLiteContext) ResultDouble(d float64) {
66 | C.sqlite3_result_double((*C.sqlite3_context)(c), C.double(d))
67 | }
68 |
69 | // ResultInt sets the result of an SQL function.
70 | // See: sqlite3_result_int, http://sqlite.org/c3ref/result_blob.html
71 | func (c *SQLiteContext) ResultInt(i int) {
72 | if i64 && (i > math.MaxInt32 || i < math.MinInt32) {
73 | C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i))
74 | } else {
75 | C.sqlite3_result_int((*C.sqlite3_context)(c), C.int(i))
76 | }
77 | }
78 |
79 | // ResultInt64 sets the result of an SQL function.
80 | // See: sqlite3_result_int64, http://sqlite.org/c3ref/result_blob.html
81 | func (c *SQLiteContext) ResultInt64(i int64) {
82 | C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i))
83 | }
84 |
85 | // ResultNull sets the result of an SQL function.
86 | // See: sqlite3_result_null, http://sqlite.org/c3ref/result_blob.html
87 | func (c *SQLiteContext) ResultNull() {
88 | C.sqlite3_result_null((*C.sqlite3_context)(c))
89 | }
90 |
91 | // ResultText sets the result of an SQL function.
92 | // See: sqlite3_result_text, http://sqlite.org/c3ref/result_blob.html
93 | func (c *SQLiteContext) ResultText(s string) {
94 | h := (*reflect.StringHeader)(unsafe.Pointer(&s))
95 | cs, l := (*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)
96 | C.my_result_text((*C.sqlite3_context)(c), cs, l)
97 | }
98 |
99 | // ResultZeroblob sets the result of an SQL function.
100 | // See: sqlite3_result_zeroblob, http://sqlite.org/c3ref/result_blob.html
101 | func (c *SQLiteContext) ResultZeroblob(n int) {
102 | C.sqlite3_result_zeroblob((*C.sqlite3_context)(c), C.int(n))
103 | }
104 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2018 G.J.R. Timmer .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | package sqlite3
7 |
8 | import (
9 | "crypto/sha1"
10 | "crypto/sha256"
11 | "crypto/sha512"
12 | )
13 |
14 | // This file provides several different implementations for the
15 | // default embedded sqlite_crypt function.
16 | // This function is uses a caesar-cypher by default
17 | // and is used within the UserAuthentication module to encode
18 | // the password.
19 | //
20 | // The provided functions can be used as an overload to the sqlite_crypt
21 | // function through the use of the RegisterFunc on the connection.
22 | //
23 | // Because the functions can serv a purpose to an end-user
24 | // without using the UserAuthentication module
25 | // the functions are default compiled in.
26 | //
27 | // From SQLITE3 - user-auth.txt
28 | // The sqlite_user.pw field is encoded by a built-in SQL function
29 | // "sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
30 | // is the plaintext password supplied to the sqlite3_user_authenticate()
31 | // interface. The second argument is the sqlite_user.pw value and is supplied
32 | // so that the function can extract the "salt" used by the password encoder.
33 | // The result of sqlite_crypt(X,Y) is another blob which is the value that
34 | // ends up being stored in sqlite_user.pw. To verify credentials X supplied
35 | // by the sqlite3_user_authenticate() routine, SQLite runs:
36 | //
37 | // sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
38 | //
39 | // To compute an appropriate sqlite_user.pw value from a new or modified
40 | // password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
41 | // when the second argument is NULL.
42 | //
43 | // The built-in version of of sqlite_crypt() uses a simple Caesar-cypher
44 | // which prevents passwords from being revealed by searching the raw database
45 | // for ASCII text, but is otherwise trivally broken. For better password
46 | // security, the database should be encrypted using the SQLite Encryption
47 | // Extension or similar technology. Or, the application can use the
48 | // sqlite3_create_function() interface to provide an alternative
49 | // implementation of sqlite_crypt() that computes a stronger password hash,
50 | // perhaps using a cryptographic hash function like SHA1.
51 |
52 | // CryptEncoderSHA1 encodes a password with SHA1
53 | func CryptEncoderSHA1(pass []byte, hash interface{}) []byte {
54 | h := sha1.Sum(pass)
55 | return h[:]
56 | }
57 |
58 | // CryptEncoderSSHA1 encodes a password with SHA1 with the
59 | // configured salt.
60 | func CryptEncoderSSHA1(salt string) func(pass []byte, hash interface{}) []byte {
61 | return func(pass []byte, hash interface{}) []byte {
62 | s := []byte(salt)
63 | p := append(pass, s...)
64 | h := sha1.Sum(p)
65 | return h[:]
66 | }
67 | }
68 |
69 | // CryptEncoderSHA256 encodes a password with SHA256
70 | func CryptEncoderSHA256(pass []byte, hash interface{}) []byte {
71 | h := sha256.Sum256(pass)
72 | return h[:]
73 | }
74 |
75 | // CryptEncoderSSHA256 encodes a password with SHA256
76 | // with the configured salt
77 | func CryptEncoderSSHA256(salt string) func(pass []byte, hash interface{}) []byte {
78 | return func(pass []byte, hash interface{}) []byte {
79 | s := []byte(salt)
80 | p := append(pass, s...)
81 | h := sha256.Sum256(p)
82 | return h[:]
83 | }
84 | }
85 |
86 | // CryptEncoderSHA384 encodes a password with SHA384
87 | func CryptEncoderSHA384(pass []byte, hash interface{}) []byte {
88 | h := sha512.Sum384(pass)
89 | return h[:]
90 | }
91 |
92 | // CryptEncoderSSHA384 encodes a password with SHA384
93 | // with the configured salt
94 | func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte {
95 | return func(pass []byte, hash interface{}) []byte {
96 | s := []byte(salt)
97 | p := append(pass, s...)
98 | h := sha512.Sum384(p)
99 | return h[:]
100 | }
101 | }
102 |
103 | // CryptEncoderSHA512 encodes a password with SHA512
104 | func CryptEncoderSHA512(pass []byte, hash interface{}) []byte {
105 | h := sha512.Sum512(pass)
106 | return h[:]
107 | }
108 |
109 | // CryptEncoderSSHA512 encodes a password with SHA512
110 | // with the configured salt
111 | func CryptEncoderSSHA512(salt string) func(pass []byte, hash interface{}) []byte {
112 | return func(pass []byte, hash interface{}) []byte {
113 | s := []byte(salt)
114 | p := append(pass, s...)
115 | h := sha512.Sum512(p)
116 | return h[:]
117 | }
118 | }
119 |
120 | // EOF
121 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build cgo
7 | // +build go1.8
8 |
9 | package sqlite3
10 |
11 | import (
12 | "database/sql/driver"
13 |
14 | "context"
15 | )
16 |
17 | // Ping implement Pinger.
18 | func (c *SQLiteConn) Ping(ctx context.Context) error {
19 | if c.db == nil {
20 | // must be ErrBadConn for sql to close the database
21 | return driver.ErrBadConn
22 | }
23 | return nil
24 | }
25 |
26 | // QueryContext implement QueryerContext.
27 | func (c *SQLiteConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
28 | list := make([]namedValue, len(args))
29 | for i, nv := range args {
30 | list[i] = namedValue(nv)
31 | }
32 | return c.query(ctx, query, list)
33 | }
34 |
35 | // ExecContext implement ExecerContext.
36 | func (c *SQLiteConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
37 | list := make([]namedValue, len(args))
38 | for i, nv := range args {
39 | list[i] = namedValue(nv)
40 | }
41 | return c.exec(ctx, query, list)
42 | }
43 |
44 | // PrepareContext implement ConnPrepareContext.
45 | func (c *SQLiteConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
46 | return c.prepare(ctx, query)
47 | }
48 |
49 | // BeginTx implement ConnBeginTx.
50 | func (c *SQLiteConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
51 | return c.begin(ctx)
52 | }
53 |
54 | // QueryContext implement QueryerContext.
55 | func (s *SQLiteStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
56 | list := make([]namedValue, len(args))
57 | for i, nv := range args {
58 | list[i] = namedValue(nv)
59 | }
60 | return s.query(ctx, list)
61 | }
62 |
63 | // ExecContext implement ExecerContext.
64 | func (s *SQLiteStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
65 | list := make([]namedValue, len(args))
66 | for i, nv := range args {
67 | list[i] = namedValue(nv)
68 | }
69 | return s.exec(ctx, list)
70 | }
71 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build libsqlite3
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo CFLAGS: -DUSE_LIBSQLITE3
12 | #cgo linux LDFLAGS: -lsqlite3
13 | #cgo darwin LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3
14 | #cgo darwin CFLAGS: -I/usr/local/opt/sqlite/include
15 | #cgo openbsd LDFLAGS: -lsqlite3
16 | #cgo solaris LDFLAGS: -lsqlite3
17 | #cgo windows LDFLAGS: -lsqlite3
18 | */
19 | import "C"
20 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build !sqlite_omit_load_extension
7 |
8 | package sqlite3
9 |
10 | /*
11 | #ifndef USE_LIBSQLITE3
12 | #include "sqlite3-binding.h"
13 | #else
14 | #include
15 | #endif
16 | #include
17 | */
18 | import "C"
19 | import (
20 | "errors"
21 | "unsafe"
22 | )
23 |
24 | func (c *SQLiteConn) loadExtensions(extensions []string) error {
25 | rv := C.sqlite3_enable_load_extension(c.db, 1)
26 | if rv != C.SQLITE_OK {
27 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
28 | }
29 |
30 | for _, extension := range extensions {
31 | if err := c.loadExtension(extension, nil); err != nil {
32 | C.sqlite3_enable_load_extension(c.db, 0)
33 | return err
34 | }
35 | }
36 |
37 | rv = C.sqlite3_enable_load_extension(c.db, 0)
38 | if rv != C.SQLITE_OK {
39 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
40 | }
41 |
42 | return nil
43 | }
44 |
45 | // LoadExtension load the sqlite3 extension.
46 | func (c *SQLiteConn) LoadExtension(lib string, entry string) error {
47 | rv := C.sqlite3_enable_load_extension(c.db, 1)
48 | if rv != C.SQLITE_OK {
49 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
50 | }
51 |
52 | if err := c.loadExtension(lib, &entry); err != nil {
53 | C.sqlite3_enable_load_extension(c.db, 0)
54 | return err
55 | }
56 |
57 | rv = C.sqlite3_enable_load_extension(c.db, 0)
58 | if rv != C.SQLITE_OK {
59 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
60 | }
61 |
62 | return nil
63 | }
64 |
65 | func (c *SQLiteConn) loadExtension(lib string, entry *string) error {
66 | clib := C.CString(lib)
67 | defer C.free(unsafe.Pointer(clib))
68 |
69 | var centry *C.char
70 | if entry != nil {
71 | centry = C.CString(*entry)
72 | defer C.free(unsafe.Pointer(centry))
73 | }
74 |
75 | var errMsg *C.char
76 | defer C.sqlite3_free(unsafe.Pointer(errMsg))
77 |
78 | rv := C.sqlite3_load_extension(c.db, clib, centry, &errMsg)
79 | if rv != C.SQLITE_OK {
80 | return errors.New(C.GoString(errMsg))
81 | }
82 |
83 | return nil
84 | }
85 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension_omit.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build sqlite_omit_load_extension
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo CFLAGS: -DSQLITE_OMIT_LOAD_EXTENSION
12 | */
13 | import "C"
14 | import (
15 | "errors"
16 | )
17 |
18 | func (c *SQLiteConn) loadExtensions(extensions []string) error {
19 | return errors.New("Extensions have been disabled for static builds")
20 | }
21 |
22 | func (c *SQLiteConn) LoadExtension(lib string, entry string) error {
23 | return errors.New("Extensions have been disabled for static builds")
24 | }
25 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_allow_uri_authority.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Copyright (C) 2018 G.J.R. Timmer .
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build sqlite_allow_uri_authority
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_ALLOW_URI_AUTHORITY
13 | #cgo LDFLAGS: -lm
14 | */
15 | import "C"
16 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_app_armor.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Copyright (C) 2018 G.J.R. Timmer .
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build !windows
8 | // +build sqlite_app_armor
9 |
10 | package sqlite3
11 |
12 | /*
13 | #cgo CFLAGS: -DSQLITE_ENABLE_API_ARMOR
14 | #cgo LDFLAGS: -lm
15 | */
16 | import "C"
17 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_column_metadata.go:
--------------------------------------------------------------------------------
1 | // +build sqlite_column_metadata
2 |
3 | package sqlite3
4 |
5 | /*
6 | #ifndef USE_LIBSQLITE3
7 | #cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA
8 | #include
9 | #else
10 | #include
11 | #endif
12 | */
13 | import "C"
14 |
15 | // ColumnTableName returns the table that is the origin of a particular result
16 | // column in a SELECT statement.
17 | //
18 | // See https://www.sqlite.org/c3ref/column_database_name.html
19 | func (s *SQLiteStmt) ColumnTableName(n int) string {
20 | return C.GoString(C.sqlite3_column_table_name(s.s, C.int(n)))
21 | }
22 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_foreign_keys.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Copyright (C) 2018 G.J.R. Timmer .
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build sqlite_foreign_keys
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_DEFAULT_FOREIGN_KEYS=1
13 | #cgo LDFLAGS: -lm
14 | */
15 | import "C"
16 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts5.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build sqlite_fts5 fts5
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo CFLAGS: -DSQLITE_ENABLE_FTS5
12 | #cgo LDFLAGS: -lm
13 | */
14 | import "C"
15 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_icu.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build sqlite_icu icu
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo LDFLAGS: -licuuc -licui18n
12 | #cgo CFLAGS: -DSQLITE_ENABLE_ICU
13 | #cgo darwin CFLAGS: -I/usr/local/opt/icu4c/include
14 | #cgo darwin LDFLAGS: -L/usr/local/opt/icu4c/lib
15 | #cgo openbsd LDFLAGS: -lsqlite3
16 | */
17 | import "C"
18 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_introspect.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Copyright (C) 2018 G.J.R. Timmer .
3 |
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build sqlite_introspect
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_INTROSPECTION_PRAGMAS
13 | #cgo LDFLAGS: -lm
14 | */
15 | import "C"
16 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_json1.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build sqlite_json sqlite_json1 json1
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo CFLAGS: -DSQLITE_ENABLE_JSON1
12 | */
13 | import "C"
14 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 G.J.R. Timmer .
2 | // Copyright (C) 2018 segment.com
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build cgo
8 |
9 | package sqlite3
10 |
11 | // SQLitePreUpdateData represents all of the data available during a
12 | // pre-update hook call.
13 | type SQLitePreUpdateData struct {
14 | Conn *SQLiteConn
15 | Op int
16 | DatabaseName string
17 | TableName string
18 | OldRowID int64
19 | NewRowID int64
20 | }
21 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 G.J.R. Timmer .
2 | // Copyright (C) 2018 segment.com
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build sqlite_preupdate_hook
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_ENABLE_PREUPDATE_HOOK
13 | #cgo LDFLAGS: -lm
14 |
15 | #ifndef USE_LIBSQLITE3
16 | #include "sqlite3-binding.h"
17 | #else
18 | #include
19 | #endif
20 | #include
21 | #include
22 |
23 | void preUpdateHookTrampoline(void*, sqlite3 *, int, char *, char *, sqlite3_int64, sqlite3_int64);
24 | */
25 | import "C"
26 | import (
27 | "errors"
28 | "unsafe"
29 | )
30 |
31 | // RegisterPreUpdateHook sets the pre-update hook for a connection.
32 | //
33 | // The callback is passed a SQLitePreUpdateData struct with the data for
34 | // the update, as well as methods for fetching copies of impacted data.
35 | //
36 | // If there is an existing update hook for this connection, it will be
37 | // removed. If callback is nil the existing hook (if any) will be removed
38 | // without creating a new one.
39 | func (c *SQLiteConn) RegisterPreUpdateHook(callback func(SQLitePreUpdateData)) {
40 | if callback == nil {
41 | C.sqlite3_preupdate_hook(c.db, nil, nil)
42 | } else {
43 | C.sqlite3_preupdate_hook(c.db, (*[0]byte)(unsafe.Pointer(C.preUpdateHookTrampoline)), unsafe.Pointer(newHandle(c, callback)))
44 | }
45 | }
46 |
47 | // Depth returns the source path of the write, see sqlite3_preupdate_depth()
48 | func (d *SQLitePreUpdateData) Depth() int {
49 | return int(C.sqlite3_preupdate_depth(d.Conn.db))
50 | }
51 |
52 | // Count returns the number of columns in the row
53 | func (d *SQLitePreUpdateData) Count() int {
54 | return int(C.sqlite3_preupdate_count(d.Conn.db))
55 | }
56 |
57 | func (d *SQLitePreUpdateData) row(dest []interface{}, new bool) error {
58 | for i := 0; i < d.Count() && i < len(dest); i++ {
59 | var val *C.sqlite3_value
60 | var src interface{}
61 |
62 | // Initially I tried making this just a function pointer argument, but
63 | // it's absurdly complicated to pass C function pointers.
64 | if new {
65 | C.sqlite3_preupdate_new(d.Conn.db, C.int(i), &val)
66 | } else {
67 | C.sqlite3_preupdate_old(d.Conn.db, C.int(i), &val)
68 | }
69 |
70 | switch C.sqlite3_value_type(val) {
71 | case C.SQLITE_INTEGER:
72 | src = int64(C.sqlite3_value_int64(val))
73 | case C.SQLITE_FLOAT:
74 | src = float64(C.sqlite3_value_double(val))
75 | case C.SQLITE_BLOB:
76 | len := C.sqlite3_value_bytes(val)
77 | blobptr := C.sqlite3_value_blob(val)
78 | src = C.GoBytes(blobptr, len)
79 | case C.SQLITE_TEXT:
80 | len := C.sqlite3_value_bytes(val)
81 | cstrptr := unsafe.Pointer(C.sqlite3_value_text(val))
82 | src = C.GoBytes(cstrptr, len)
83 | case C.SQLITE_NULL:
84 | src = nil
85 | }
86 |
87 | err := convertAssign(&dest[i], src)
88 | if err != nil {
89 | return err
90 | }
91 | }
92 |
93 | return nil
94 | }
95 |
96 | // Old populates dest with the row data to be replaced. This works similar to
97 | // database/sql's Rows.Scan()
98 | func (d *SQLitePreUpdateData) Old(dest ...interface{}) error {
99 | if d.Op == SQLITE_INSERT {
100 | return errors.New("There is no old row for INSERT operations")
101 | }
102 | return d.row(dest, false)
103 | }
104 |
105 | // New populates dest with the replacement row data. This works similar to
106 | // database/sql's Rows.Scan()
107 | func (d *SQLitePreUpdateData) New(dest ...interface{}) error {
108 | if d.Op == SQLITE_DELETE {
109 | return errors.New("There is no new row for DELETE operations")
110 | }
111 | return d.row(dest, true)
112 | }
113 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_omit.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 G.J.R. Timmer .
2 | // Copyright (C) 2018 segment.com
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build !sqlite_preupdate_hook,cgo
8 |
9 | package sqlite3
10 |
11 | // RegisterPreUpdateHook sets the pre-update hook for a connection.
12 | //
13 | // The callback is passed a SQLitePreUpdateData struct with the data for
14 | // the update, as well as methods for fetching copies of impacted data.
15 | //
16 | // If there is an existing update hook for this connection, it will be
17 | // removed. If callback is nil the existing hook (if any) will be removed
18 | // without creating a new one.
19 | func (c *SQLiteConn) RegisterPreUpdateHook(callback func(SQLitePreUpdateData)) {
20 | // NOOP
21 | }
22 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Copyright (C) 2018 G.J.R. Timmer .
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build sqlite_secure_delete
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_SECURE_DELETE=1
13 | #cgo LDFLAGS: -lm
14 | */
15 | import "C"
16 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete_fast.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Copyright (C) 2018 G.J.R. Timmer .
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build sqlite_secure_delete_fast
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_SECURE_DELETE=FAST
13 | #cgo LDFLAGS: -lm
14 | */
15 | import "C"
16 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_stat4.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Copyright (C) 2018 G.J.R. Timmer .
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build sqlite_stat4
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_ENABLE_STAT4
13 | #cgo LDFLAGS: -lm
14 | */
15 | import "C"
16 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.c:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2018 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
7 | #include
8 | #include "sqlite3-binding.h"
9 |
10 | extern int unlock_notify_wait(sqlite3 *db);
11 |
12 | int
13 | _sqlite3_step_blocking(sqlite3_stmt *stmt)
14 | {
15 | int rv;
16 | sqlite3* db;
17 |
18 | db = sqlite3_db_handle(stmt);
19 | for (;;) {
20 | rv = sqlite3_step(stmt);
21 | if (rv != SQLITE_LOCKED) {
22 | break;
23 | }
24 | if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) {
25 | break;
26 | }
27 | rv = unlock_notify_wait(db);
28 | if (rv != SQLITE_OK) {
29 | break;
30 | }
31 | sqlite3_reset(stmt);
32 | }
33 |
34 | return rv;
35 | }
36 |
37 | int
38 | _sqlite3_step_row_blocking(sqlite3_stmt* stmt, long long* rowid, long long* changes)
39 | {
40 | int rv;
41 | sqlite3* db;
42 |
43 | db = sqlite3_db_handle(stmt);
44 | for (;;) {
45 | rv = sqlite3_step(stmt);
46 | if (rv!=SQLITE_LOCKED) {
47 | break;
48 | }
49 | if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) {
50 | break;
51 | }
52 | rv = unlock_notify_wait(db);
53 | if (rv != SQLITE_OK) {
54 | break;
55 | }
56 | sqlite3_reset(stmt);
57 | }
58 |
59 | *rowid = (long long) sqlite3_last_insert_rowid(db);
60 | *changes = (long long) sqlite3_changes(db);
61 | return rv;
62 | }
63 |
64 | int
65 | _sqlite3_prepare_v2_blocking(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail)
66 | {
67 | int rv;
68 |
69 | for (;;) {
70 | rv = sqlite3_prepare_v2(db, zSql, nBytes, ppStmt, pzTail);
71 | if (rv!=SQLITE_LOCKED) {
72 | break;
73 | }
74 | if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) {
75 | break;
76 | }
77 | rv = unlock_notify_wait(db);
78 | if (rv != SQLITE_OK) {
79 | break;
80 | }
81 | }
82 |
83 | return rv;
84 | }
85 | #endif
86 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build cgo
7 | // +build sqlite_unlock_notify
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_ENABLE_UNLOCK_NOTIFY
13 |
14 | #include
15 | #include "sqlite3-binding.h"
16 |
17 | extern void unlock_notify_callback(void *arg, int argc);
18 | */
19 | import "C"
20 | import (
21 | "fmt"
22 | "math"
23 | "sync"
24 | "unsafe"
25 | )
26 |
27 | type unlock_notify_table struct {
28 | sync.Mutex
29 | seqnum uint
30 | table map[uint]chan struct{}
31 | }
32 |
33 | var unt unlock_notify_table = unlock_notify_table{table: make(map[uint]chan struct{})}
34 |
35 | func (t *unlock_notify_table) add(c chan struct{}) uint {
36 | t.Lock()
37 | defer t.Unlock()
38 | h := t.seqnum
39 | t.table[h] = c
40 | t.seqnum++
41 | return h
42 | }
43 |
44 | func (t *unlock_notify_table) remove(h uint) {
45 | t.Lock()
46 | defer t.Unlock()
47 | delete(t.table, h)
48 | }
49 |
50 | func (t *unlock_notify_table) get(h uint) chan struct{} {
51 | t.Lock()
52 | defer t.Unlock()
53 | c, ok := t.table[h]
54 | if !ok {
55 | panic(fmt.Sprintf("Non-existent key for unlcok-notify channel: %d", h))
56 | }
57 | return c
58 | }
59 |
60 | //export unlock_notify_callback
61 | func unlock_notify_callback(argv unsafe.Pointer, argc C.int) {
62 | for i := 0; i < int(argc); i++ {
63 | parg := ((*(*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.uint)(nil))]*[1]uint)(argv))[i])
64 | arg := *parg
65 | h := arg[0]
66 | c := unt.get(h)
67 | c <- struct{}{}
68 | }
69 | }
70 |
71 | //export unlock_notify_wait
72 | func unlock_notify_wait(db *C.sqlite3) C.int {
73 | // It has to be a bufferred channel to not block in sqlite_unlock_notify
74 | // as sqlite_unlock_notify could invoke the callback before it returns.
75 | c := make(chan struct{}, 1)
76 | defer close(c)
77 |
78 | h := unt.add(c)
79 | defer unt.remove(h)
80 |
81 | pargv := C.malloc(C.sizeof_uint)
82 | defer C.free(pargv)
83 |
84 | argv := (*[1]uint)(pargv)
85 | argv[0] = h
86 | if rv := C.sqlite3_unlock_notify(db, (*[0]byte)(C.unlock_notify_callback), unsafe.Pointer(pargv)); rv != C.SQLITE_OK {
87 | return rv
88 | }
89 |
90 | <-c
91 |
92 | return C.SQLITE_OK
93 | }
94 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2018 G.J.R. Timmer .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build sqlite_userauth
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo CFLAGS: -DSQLITE_USER_AUTHENTICATION
12 | #cgo LDFLAGS: -lm
13 | #ifndef USE_LIBSQLITE3
14 | #include "sqlite3-binding.h"
15 | #else
16 | #include
17 | #endif
18 | #include
19 |
20 | static int
21 | _sqlite3_user_authenticate(sqlite3* db, const char* zUsername, const char* aPW, int nPW)
22 | {
23 | return sqlite3_user_authenticate(db, zUsername, aPW, nPW);
24 | }
25 |
26 | static int
27 | _sqlite3_user_add(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin)
28 | {
29 | return sqlite3_user_add(db, zUsername, aPW, nPW, isAdmin);
30 | }
31 |
32 | static int
33 | _sqlite3_user_change(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin)
34 | {
35 | return sqlite3_user_change(db, zUsername, aPW, nPW, isAdmin);
36 | }
37 |
38 | static int
39 | _sqlite3_user_delete(sqlite3* db, const char* zUsername)
40 | {
41 | return sqlite3_user_delete(db, zUsername);
42 | }
43 |
44 | static int
45 | _sqlite3_auth_enabled(sqlite3* db)
46 | {
47 | int exists = -1;
48 |
49 | sqlite3_stmt *stmt;
50 | sqlite3_prepare_v2(db, "select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';", -1, &stmt, NULL);
51 |
52 | while ( sqlite3_step(stmt) == SQLITE_ROW) {
53 | exists = sqlite3_column_int(stmt, 0);
54 | }
55 |
56 | sqlite3_finalize(stmt);
57 |
58 | return exists;
59 | }
60 | */
61 | import "C"
62 | import (
63 | "errors"
64 | "unsafe"
65 | )
66 |
67 | const (
68 | SQLITE_AUTH = C.SQLITE_AUTH
69 | )
70 |
71 | var (
72 | ErrUnauthorized = errors.New("SQLITE_AUTH: Unauthorized")
73 | ErrAdminRequired = errors.New("SQLITE_AUTH: Unauthorized; Admin Privileges Required")
74 | )
75 |
76 | // Authenticate will perform an authentication of the provided username
77 | // and password against the database.
78 | //
79 | // If a database contains the SQLITE_USER table, then the
80 | // call to Authenticate must be invoked with an
81 | // appropriate username and password prior to enable read and write
82 | //access to the database.
83 | //
84 | // Return SQLITE_OK on success or SQLITE_ERROR if the username/password
85 | // combination is incorrect or unknown.
86 | //
87 | // If the SQLITE_USER table is not present in the database file, then
88 | // this interface is a harmless no-op returnning SQLITE_OK.
89 | func (c *SQLiteConn) Authenticate(username, password string) error {
90 | rv := c.authenticate(username, password)
91 | switch rv {
92 | case C.SQLITE_ERROR, C.SQLITE_AUTH:
93 | return ErrUnauthorized
94 | case C.SQLITE_OK:
95 | return nil
96 | default:
97 | return c.lastError()
98 | }
99 | }
100 |
101 | // authenticate provides the actual authentication to SQLite.
102 | // This is not exported for usage in Go.
103 | // It is however exported for usage within SQL by the user.
104 | //
105 | // Returns:
106 | // C.SQLITE_OK (0)
107 | // C.SQLITE_ERROR (1)
108 | // C.SQLITE_AUTH (23)
109 | func (c *SQLiteConn) authenticate(username, password string) int {
110 | // Allocate C Variables
111 | cuser := C.CString(username)
112 | cpass := C.CString(password)
113 |
114 | // Free C Variables
115 | defer func() {
116 | C.free(unsafe.Pointer(cuser))
117 | C.free(unsafe.Pointer(cpass))
118 | }()
119 |
120 | return int(C._sqlite3_user_authenticate(c.db, cuser, cpass, C.int(len(password))))
121 | }
122 |
123 | // AuthUserAdd can be used (by an admin user only)
124 | // to create a new user. When called on a no-authentication-required
125 | // database, this routine converts the database into an authentication-
126 | // required database, automatically makes the added user an
127 | // administrator, and logs in the current connection as that user.
128 | // The AuthUserAdd only works for the "main" database, not
129 | // for any ATTACH-ed databases. Any call to AuthUserAdd by a
130 | // non-admin user results in an error.
131 | func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error {
132 | isAdmin := 0
133 | if admin {
134 | isAdmin = 1
135 | }
136 |
137 | rv := c.authUserAdd(username, password, isAdmin)
138 | switch rv {
139 | case C.SQLITE_ERROR, C.SQLITE_AUTH:
140 | return ErrAdminRequired
141 | case C.SQLITE_OK:
142 | return nil
143 | default:
144 | return c.lastError()
145 | }
146 | }
147 |
148 | // authUserAdd enables the User Authentication if not enabled.
149 | // Otherwise it will add a user.
150 | //
151 | // When user authentication is already enabled then this function
152 | // can only be called by an admin.
153 | //
154 | // This is not exported for usage in Go.
155 | // It is however exported for usage within SQL by the user.
156 | //
157 | // Returns:
158 | // C.SQLITE_OK (0)
159 | // C.SQLITE_ERROR (1)
160 | // C.SQLITE_AUTH (23)
161 | func (c *SQLiteConn) authUserAdd(username, password string, admin int) int {
162 | // Allocate C Variables
163 | cuser := C.CString(username)
164 | cpass := C.CString(password)
165 |
166 | // Free C Variables
167 | defer func() {
168 | C.free(unsafe.Pointer(cuser))
169 | C.free(unsafe.Pointer(cpass))
170 | }()
171 |
172 | return int(C._sqlite3_user_add(c.db, cuser, cpass, C.int(len(password)), C.int(admin)))
173 | }
174 |
175 | // AuthUserChange can be used to change a users
176 | // login credentials or admin privilege. Any user can change their own
177 | // login credentials. Only an admin user can change another users login
178 | // credentials or admin privilege setting. No user may change their own
179 | // admin privilege setting.
180 | func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error {
181 | isAdmin := 0
182 | if admin {
183 | isAdmin = 1
184 | }
185 |
186 | rv := c.authUserChange(username, password, isAdmin)
187 | switch rv {
188 | case C.SQLITE_ERROR, C.SQLITE_AUTH:
189 | return ErrAdminRequired
190 | case C.SQLITE_OK:
191 | return nil
192 | default:
193 | return c.lastError()
194 | }
195 | }
196 |
197 | // authUserChange allows to modify a user.
198 | // Users can change their own password.
199 | //
200 | // Only admins can change passwords for other users
201 | // and modify the admin flag.
202 | //
203 | // The admin flag of the current logged in user cannot be changed.
204 | // THis ensures that their is always an admin.
205 | //
206 | // This is not exported for usage in Go.
207 | // It is however exported for usage within SQL by the user.
208 | //
209 | // Returns:
210 | // C.SQLITE_OK (0)
211 | // C.SQLITE_ERROR (1)
212 | // C.SQLITE_AUTH (23)
213 | func (c *SQLiteConn) authUserChange(username, password string, admin int) int {
214 | // Allocate C Variables
215 | cuser := C.CString(username)
216 | cpass := C.CString(password)
217 |
218 | // Free C Variables
219 | defer func() {
220 | C.free(unsafe.Pointer(cuser))
221 | C.free(unsafe.Pointer(cpass))
222 | }()
223 |
224 | return int(C._sqlite3_user_change(c.db, cuser, cpass, C.int(len(password)), C.int(admin)))
225 | }
226 |
227 | // AuthUserDelete can be used (by an admin user only)
228 | // to delete a user. The currently logged-in user cannot be deleted,
229 | // which guarantees that there is always an admin user and hence that
230 | // the database cannot be converted into a no-authentication-required
231 | // database.
232 | func (c *SQLiteConn) AuthUserDelete(username string) error {
233 | rv := c.authUserDelete(username)
234 | switch rv {
235 | case C.SQLITE_ERROR, C.SQLITE_AUTH:
236 | return ErrAdminRequired
237 | case C.SQLITE_OK:
238 | return nil
239 | default:
240 | return c.lastError()
241 | }
242 | }
243 |
244 | // authUserDelete can be used to delete a user.
245 | //
246 | // This function can only be executed by an admin.
247 | //
248 | // This is not exported for usage in Go.
249 | // It is however exported for usage within SQL by the user.
250 | //
251 | // Returns:
252 | // C.SQLITE_OK (0)
253 | // C.SQLITE_ERROR (1)
254 | // C.SQLITE_AUTH (23)
255 | func (c *SQLiteConn) authUserDelete(username string) int {
256 | // Allocate C Variables
257 | cuser := C.CString(username)
258 |
259 | // Free C Variables
260 | defer func() {
261 | C.free(unsafe.Pointer(cuser))
262 | }()
263 |
264 | return int(C._sqlite3_user_delete(c.db, cuser))
265 | }
266 |
267 | // AuthEnabled checks if the database is protected by user authentication
268 | func (c *SQLiteConn) AuthEnabled() (exists bool) {
269 | rv := c.authEnabled()
270 | if rv == 1 {
271 | exists = true
272 | }
273 |
274 | return
275 | }
276 |
277 | // authEnabled perform the actual check for user authentication.
278 | //
279 | // This is not exported for usage in Go.
280 | // It is however exported for usage within SQL by the user.
281 | //
282 | // Returns:
283 | // 0 - Disabled
284 | // 1 - Enabled
285 | func (c *SQLiteConn) authEnabled() int {
286 | return int(C._sqlite3_auth_enabled(c.db))
287 | }
288 |
289 | // EOF
290 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_omit.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2018 G.J.R. Timmer .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build !sqlite_userauth
7 |
8 | package sqlite3
9 |
10 | import (
11 | "C"
12 | )
13 |
14 | // Authenticate will perform an authentication of the provided username
15 | // and password against the database.
16 | //
17 | // If a database contains the SQLITE_USER table, then the
18 | // call to Authenticate must be invoked with an
19 | // appropriate username and password prior to enable read and write
20 | //access to the database.
21 | //
22 | // Return SQLITE_OK on success or SQLITE_ERROR if the username/password
23 | // combination is incorrect or unknown.
24 | //
25 | // If the SQLITE_USER table is not present in the database file, then
26 | // this interface is a harmless no-op returnning SQLITE_OK.
27 | func (c *SQLiteConn) Authenticate(username, password string) error {
28 | // NOOP
29 | return nil
30 | }
31 |
32 | // authenticate provides the actual authentication to SQLite.
33 | // This is not exported for usage in Go.
34 | // It is however exported for usage within SQL by the user.
35 | //
36 | // Returns:
37 | // C.SQLITE_OK (0)
38 | // C.SQLITE_ERROR (1)
39 | // C.SQLITE_AUTH (23)
40 | func (c *SQLiteConn) authenticate(username, password string) int {
41 | // NOOP
42 | return 0
43 | }
44 |
45 | // AuthUserAdd can be used (by an admin user only)
46 | // to create a new user. When called on a no-authentication-required
47 | // database, this routine converts the database into an authentication-
48 | // required database, automatically makes the added user an
49 | // administrator, and logs in the current connection as that user.
50 | // The AuthUserAdd only works for the "main" database, not
51 | // for any ATTACH-ed databases. Any call to AuthUserAdd by a
52 | // non-admin user results in an error.
53 | func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error {
54 | // NOOP
55 | return nil
56 | }
57 |
58 | // authUserAdd enables the User Authentication if not enabled.
59 | // Otherwise it will add a user.
60 | //
61 | // When user authentication is already enabled then this function
62 | // can only be called by an admin.
63 | //
64 | // This is not exported for usage in Go.
65 | // It is however exported for usage within SQL by the user.
66 | //
67 | // Returns:
68 | // C.SQLITE_OK (0)
69 | // C.SQLITE_ERROR (1)
70 | // C.SQLITE_AUTH (23)
71 | func (c *SQLiteConn) authUserAdd(username, password string, admin int) int {
72 | // NOOP
73 | return 0
74 | }
75 |
76 | // AuthUserChange can be used to change a users
77 | // login credentials or admin privilege. Any user can change their own
78 | // login credentials. Only an admin user can change another users login
79 | // credentials or admin privilege setting. No user may change their own
80 | // admin privilege setting.
81 | func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error {
82 | // NOOP
83 | return nil
84 | }
85 |
86 | // authUserChange allows to modify a user.
87 | // Users can change their own password.
88 | //
89 | // Only admins can change passwords for other users
90 | // and modify the admin flag.
91 | //
92 | // The admin flag of the current logged in user cannot be changed.
93 | // THis ensures that their is always an admin.
94 | //
95 | // This is not exported for usage in Go.
96 | // It is however exported for usage within SQL by the user.
97 | //
98 | // Returns:
99 | // C.SQLITE_OK (0)
100 | // C.SQLITE_ERROR (1)
101 | // C.SQLITE_AUTH (23)
102 | func (c *SQLiteConn) authUserChange(username, password string, admin int) int {
103 | // NOOP
104 | return 0
105 | }
106 |
107 | // AuthUserDelete can be used (by an admin user only)
108 | // to delete a user. The currently logged-in user cannot be deleted,
109 | // which guarantees that there is always an admin user and hence that
110 | // the database cannot be converted into a no-authentication-required
111 | // database.
112 | func (c *SQLiteConn) AuthUserDelete(username string) error {
113 | // NOOP
114 | return nil
115 | }
116 |
117 | // authUserDelete can be used to delete a user.
118 | //
119 | // This function can only be executed by an admin.
120 | //
121 | // This is not exported for usage in Go.
122 | // It is however exported for usage within SQL by the user.
123 | //
124 | // Returns:
125 | // C.SQLITE_OK (0)
126 | // C.SQLITE_ERROR (1)
127 | // C.SQLITE_AUTH (23)
128 | func (c *SQLiteConn) authUserDelete(username string) int {
129 | // NOOP
130 | return 0
131 | }
132 |
133 | // AuthEnabled checks if the database is protected by user authentication
134 | func (c *SQLiteConn) AuthEnabled() (exists bool) {
135 | // NOOP
136 | return false
137 | }
138 |
139 | // authEnabled perform the actual check for user authentication.
140 | //
141 | // This is not exported for usage in Go.
142 | // It is however exported for usage within SQL by the user.
143 | //
144 | // Returns:
145 | // 0 - Disabled
146 | // 1 - Enabled
147 | func (c *SQLiteConn) authEnabled() int {
148 | // NOOP
149 | return 0
150 | }
151 |
152 | // EOF
153 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_full.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Copyright (C) 2018 G.J.R. Timmer .
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build sqlite_vacuum_full
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=1
13 | #cgo LDFLAGS: -lm
14 | */
15 | import "C"
16 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_incr.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Copyright (C) 2018 G.J.R. Timmer .
3 | //
4 | // Use of this source code is governed by an MIT-style
5 | // license that can be found in the LICENSE file.
6 |
7 | // +build sqlite_vacuum_incr
8 |
9 | package sqlite3
10 |
11 | /*
12 | #cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=2
13 | #cgo LDFLAGS: -lm
14 | */
15 | import "C"
16 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build sqlite_vtable vtable
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo CFLAGS: -std=gnu99
12 | #cgo CFLAGS: -DSQLITE_ENABLE_RTREE
13 | #cgo CFLAGS: -DSQLITE_THREADSAFE
14 | #cgo CFLAGS: -DSQLITE_ENABLE_FTS3
15 | #cgo CFLAGS: -DSQLITE_ENABLE_FTS3_PARENTHESIS
16 | #cgo CFLAGS: -DSQLITE_ENABLE_FTS4_UNICODE61
17 | #cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
18 | #cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA=1
19 | #cgo CFLAGS: -Wno-deprecated-declarations
20 |
21 | #ifndef USE_LIBSQLITE3
22 | #include "sqlite3-binding.h"
23 | #else
24 | #include
25 | #endif
26 | #include
27 | #include
28 | #include
29 |
30 | static inline char *_sqlite3_mprintf(char *zFormat, char *arg) {
31 | return sqlite3_mprintf(zFormat, arg);
32 | }
33 |
34 | typedef struct goVTab goVTab;
35 |
36 | struct goVTab {
37 | sqlite3_vtab base;
38 | void *vTab;
39 | };
40 |
41 | uintptr_t goMInit(void *db, void *pAux, int argc, char **argv, char **pzErr, int isCreate);
42 |
43 | static int cXInit(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr, int isCreate) {
44 | void *vTab = (void *)goMInit(db, pAux, argc, (char**)argv, pzErr, isCreate);
45 | if (!vTab || *pzErr) {
46 | return SQLITE_ERROR;
47 | }
48 | goVTab *pvTab = (goVTab *)sqlite3_malloc(sizeof(goVTab));
49 | if (!pvTab) {
50 | *pzErr = sqlite3_mprintf("%s", "Out of memory");
51 | return SQLITE_NOMEM;
52 | }
53 | memset(pvTab, 0, sizeof(goVTab));
54 | pvTab->vTab = vTab;
55 |
56 | *ppVTab = (sqlite3_vtab *)pvTab;
57 | *pzErr = 0;
58 | return SQLITE_OK;
59 | }
60 |
61 | static inline int cXCreate(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
62 | return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 1);
63 | }
64 | static inline int cXConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
65 | return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 0);
66 | }
67 |
68 | char* goVBestIndex(void *pVTab, void *icp);
69 |
70 | static inline int cXBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *info) {
71 | char *pzErr = goVBestIndex(((goVTab*)pVTab)->vTab, info);
72 | if (pzErr) {
73 | if (pVTab->zErrMsg)
74 | sqlite3_free(pVTab->zErrMsg);
75 | pVTab->zErrMsg = pzErr;
76 | return SQLITE_ERROR;
77 | }
78 | return SQLITE_OK;
79 | }
80 |
81 | char* goVRelease(void *pVTab, int isDestroy);
82 |
83 | static int cXRelease(sqlite3_vtab *pVTab, int isDestroy) {
84 | char *pzErr = goVRelease(((goVTab*)pVTab)->vTab, isDestroy);
85 | if (pzErr) {
86 | if (pVTab->zErrMsg)
87 | sqlite3_free(pVTab->zErrMsg);
88 | pVTab->zErrMsg = pzErr;
89 | return SQLITE_ERROR;
90 | }
91 | if (pVTab->zErrMsg)
92 | sqlite3_free(pVTab->zErrMsg);
93 | sqlite3_free(pVTab);
94 | return SQLITE_OK;
95 | }
96 |
97 | static inline int cXDisconnect(sqlite3_vtab *pVTab) {
98 | return cXRelease(pVTab, 0);
99 | }
100 | static inline int cXDestroy(sqlite3_vtab *pVTab) {
101 | return cXRelease(pVTab, 1);
102 | }
103 |
104 | typedef struct goVTabCursor goVTabCursor;
105 |
106 | struct goVTabCursor {
107 | sqlite3_vtab_cursor base;
108 | void *vTabCursor;
109 | };
110 |
111 | uintptr_t goVOpen(void *pVTab, char **pzErr);
112 |
113 | static int cXOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
114 | void *vTabCursor = (void *)goVOpen(((goVTab*)pVTab)->vTab, &(pVTab->zErrMsg));
115 | goVTabCursor *pCursor = (goVTabCursor *)sqlite3_malloc(sizeof(goVTabCursor));
116 | if (!pCursor) {
117 | return SQLITE_NOMEM;
118 | }
119 | memset(pCursor, 0, sizeof(goVTabCursor));
120 | pCursor->vTabCursor = vTabCursor;
121 | *ppCursor = (sqlite3_vtab_cursor *)pCursor;
122 | return SQLITE_OK;
123 | }
124 |
125 | static int setErrMsg(sqlite3_vtab_cursor *pCursor, char *pzErr) {
126 | if (pCursor->pVtab->zErrMsg)
127 | sqlite3_free(pCursor->pVtab->zErrMsg);
128 | pCursor->pVtab->zErrMsg = pzErr;
129 | return SQLITE_ERROR;
130 | }
131 |
132 | char* goVClose(void *pCursor);
133 |
134 | static int cXClose(sqlite3_vtab_cursor *pCursor) {
135 | char *pzErr = goVClose(((goVTabCursor*)pCursor)->vTabCursor);
136 | if (pzErr) {
137 | return setErrMsg(pCursor, pzErr);
138 | }
139 | sqlite3_free(pCursor);
140 | return SQLITE_OK;
141 | }
142 |
143 | char* goVFilter(void *pCursor, int idxNum, char* idxName, int argc, sqlite3_value **argv);
144 |
145 | static int cXFilter(sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) {
146 | char *pzErr = goVFilter(((goVTabCursor*)pCursor)->vTabCursor, idxNum, (char*)idxStr, argc, argv);
147 | if (pzErr) {
148 | return setErrMsg(pCursor, pzErr);
149 | }
150 | return SQLITE_OK;
151 | }
152 |
153 | char* goVNext(void *pCursor);
154 |
155 | static int cXNext(sqlite3_vtab_cursor *pCursor) {
156 | char *pzErr = goVNext(((goVTabCursor*)pCursor)->vTabCursor);
157 | if (pzErr) {
158 | return setErrMsg(pCursor, pzErr);
159 | }
160 | return SQLITE_OK;
161 | }
162 |
163 | int goVEof(void *pCursor);
164 |
165 | static inline int cXEof(sqlite3_vtab_cursor *pCursor) {
166 | return goVEof(((goVTabCursor*)pCursor)->vTabCursor);
167 | }
168 |
169 | char* goVColumn(void *pCursor, void *cp, int col);
170 |
171 | static int cXColumn(sqlite3_vtab_cursor *pCursor, sqlite3_context *ctx, int i) {
172 | char *pzErr = goVColumn(((goVTabCursor*)pCursor)->vTabCursor, ctx, i);
173 | if (pzErr) {
174 | return setErrMsg(pCursor, pzErr);
175 | }
176 | return SQLITE_OK;
177 | }
178 |
179 | char* goVRowid(void *pCursor, sqlite3_int64 *pRowid);
180 |
181 | static int cXRowid(sqlite3_vtab_cursor *pCursor, sqlite3_int64 *pRowid) {
182 | char *pzErr = goVRowid(((goVTabCursor*)pCursor)->vTabCursor, pRowid);
183 | if (pzErr) {
184 | return setErrMsg(pCursor, pzErr);
185 | }
186 | return SQLITE_OK;
187 | }
188 |
189 | char* goVUpdate(void *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid);
190 |
191 | static int cXUpdate(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid) {
192 | char *pzErr = goVUpdate(((goVTab*)pVTab)->vTab, argc, argv, pRowid);
193 | if (pzErr) {
194 | if (pVTab->zErrMsg)
195 | sqlite3_free(pVTab->zErrMsg);
196 | pVTab->zErrMsg = pzErr;
197 | return SQLITE_ERROR;
198 | }
199 | return SQLITE_OK;
200 | }
201 |
202 | static sqlite3_module goModule = {
203 | 0, // iVersion
204 | cXCreate, // xCreate - create a table
205 | cXConnect, // xConnect - connect to an existing table
206 | cXBestIndex, // xBestIndex - Determine search strategy
207 | cXDisconnect, // xDisconnect - Disconnect from a table
208 | cXDestroy, // xDestroy - Drop a table
209 | cXOpen, // xOpen - open a cursor
210 | cXClose, // xClose - close a cursor
211 | cXFilter, // xFilter - configure scan constraints
212 | cXNext, // xNext - advance a cursor
213 | cXEof, // xEof
214 | cXColumn, // xColumn - read data
215 | cXRowid, // xRowid - read data
216 | cXUpdate, // xUpdate - write data
217 | // Not implemented
218 | 0, // xBegin - begin transaction
219 | 0, // xSync - sync transaction
220 | 0, // xCommit - commit transaction
221 | 0, // xRollback - rollback transaction
222 | 0, // xFindFunction - function overloading
223 | 0, // xRename - rename the table
224 | 0, // xSavepoint
225 | 0, // xRelease
226 | 0 // xRollbackTo
227 | };
228 |
229 | // See https://sqlite.org/vtab.html#eponymous_only_virtual_tables
230 | static sqlite3_module goModuleEponymousOnly = {
231 | 0, // iVersion
232 | 0, // xCreate - create a table, which here is null
233 | cXConnect, // xConnect - connect to an existing table
234 | cXBestIndex, // xBestIndex - Determine search strategy
235 | cXDisconnect, // xDisconnect - Disconnect from a table
236 | cXDestroy, // xDestroy - Drop a table
237 | cXOpen, // xOpen - open a cursor
238 | cXClose, // xClose - close a cursor
239 | cXFilter, // xFilter - configure scan constraints
240 | cXNext, // xNext - advance a cursor
241 | cXEof, // xEof
242 | cXColumn, // xColumn - read data
243 | cXRowid, // xRowid - read data
244 | cXUpdate, // xUpdate - write data
245 | // Not implemented
246 | 0, // xBegin - begin transaction
247 | 0, // xSync - sync transaction
248 | 0, // xCommit - commit transaction
249 | 0, // xRollback - rollback transaction
250 | 0, // xFindFunction - function overloading
251 | 0, // xRename - rename the table
252 | 0, // xSavepoint
253 | 0, // xRelease
254 | 0 // xRollbackTo
255 | };
256 |
257 | void goMDestroy(void*);
258 |
259 | static int _sqlite3_create_module(sqlite3 *db, const char *zName, uintptr_t pClientData) {
260 | return sqlite3_create_module_v2(db, zName, &goModule, (void*) pClientData, goMDestroy);
261 | }
262 |
263 | static int _sqlite3_create_module_eponymous_only(sqlite3 *db, const char *zName, uintptr_t pClientData) {
264 | return sqlite3_create_module_v2(db, zName, &goModuleEponymousOnly, (void*) pClientData, goMDestroy);
265 | }
266 | */
267 | import "C"
268 |
269 | import (
270 | "fmt"
271 | "math"
272 | "reflect"
273 | "unsafe"
274 | )
275 |
276 | type sqliteModule struct {
277 | c *SQLiteConn
278 | name string
279 | module Module
280 | }
281 |
282 | type sqliteVTab struct {
283 | module *sqliteModule
284 | vTab VTab
285 | }
286 |
287 | type sqliteVTabCursor struct {
288 | vTab *sqliteVTab
289 | vTabCursor VTabCursor
290 | }
291 |
292 | // Op is type of operations.
293 | type Op uint8
294 |
295 | // Op mean identity of operations.
296 | const (
297 | OpEQ Op = 2
298 | OpGT = 4
299 | OpLE = 8
300 | OpLT = 16
301 | OpGE = 32
302 | OpMATCH = 64
303 | OpLIKE = 65 /* 3.10.0 and later only */
304 | OpGLOB = 66 /* 3.10.0 and later only */
305 | OpREGEXP = 67 /* 3.10.0 and later only */
306 | OpScanUnique = 1 /* Scan visits at most 1 row */
307 | )
308 |
309 | // InfoConstraint give information of constraint.
310 | type InfoConstraint struct {
311 | Column int
312 | Op Op
313 | Usable bool
314 | }
315 |
316 | // InfoOrderBy give information of order-by.
317 | type InfoOrderBy struct {
318 | Column int
319 | Desc bool
320 | }
321 |
322 | func constraints(info *C.sqlite3_index_info) []InfoConstraint {
323 | slice := *(*[]C.struct_sqlite3_index_constraint)(unsafe.Pointer(&reflect.SliceHeader{
324 | Data: uintptr(unsafe.Pointer(info.aConstraint)),
325 | Len: int(info.nConstraint),
326 | Cap: int(info.nConstraint),
327 | }))
328 |
329 | cst := make([]InfoConstraint, 0, len(slice))
330 | for _, c := range slice {
331 | var usable bool
332 | if c.usable > 0 {
333 | usable = true
334 | }
335 | cst = append(cst, InfoConstraint{
336 | Column: int(c.iColumn),
337 | Op: Op(c.op),
338 | Usable: usable,
339 | })
340 | }
341 | return cst
342 | }
343 |
344 | func orderBys(info *C.sqlite3_index_info) []InfoOrderBy {
345 | slice := *(*[]C.struct_sqlite3_index_orderby)(unsafe.Pointer(&reflect.SliceHeader{
346 | Data: uintptr(unsafe.Pointer(info.aOrderBy)),
347 | Len: int(info.nOrderBy),
348 | Cap: int(info.nOrderBy),
349 | }))
350 |
351 | ob := make([]InfoOrderBy, 0, len(slice))
352 | for _, c := range slice {
353 | var desc bool
354 | if c.desc > 0 {
355 | desc = true
356 | }
357 | ob = append(ob, InfoOrderBy{
358 | Column: int(c.iColumn),
359 | Desc: desc,
360 | })
361 | }
362 | return ob
363 | }
364 |
365 | // IndexResult is a Go struct representation of what eventually ends up in the
366 | // output fields for `sqlite3_index_info`
367 | // See: https://www.sqlite.org/c3ref/index_info.html
368 | type IndexResult struct {
369 | Used []bool // aConstraintUsage
370 | IdxNum int
371 | IdxStr string
372 | AlreadyOrdered bool // orderByConsumed
373 | EstimatedCost float64
374 | EstimatedRows float64
375 | }
376 |
377 | // mPrintf is a utility wrapper around sqlite3_mprintf
378 | func mPrintf(format, arg string) *C.char {
379 | cf := C.CString(format)
380 | defer C.free(unsafe.Pointer(cf))
381 | ca := C.CString(arg)
382 | defer C.free(unsafe.Pointer(ca))
383 | return C._sqlite3_mprintf(cf, ca)
384 | }
385 |
386 | //export goMInit
387 | func goMInit(db, pClientData unsafe.Pointer, argc C.int, argv **C.char, pzErr **C.char, isCreate C.int) C.uintptr_t {
388 | m := lookupHandle(pClientData).(*sqliteModule)
389 | if m.c.db != (*C.sqlite3)(db) {
390 | *pzErr = mPrintf("%s", "Inconsistent db handles")
391 | return 0
392 | }
393 | args := make([]string, argc)
394 | var A []*C.char
395 | slice := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(argv)), Len: int(argc), Cap: int(argc)}
396 | a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
397 | for i, s := range a.([]*C.char) {
398 | args[i] = C.GoString(s)
399 | }
400 | var vTab VTab
401 | var err error
402 | if isCreate == 1 {
403 | vTab, err = m.module.Create(m.c, args)
404 | } else {
405 | vTab, err = m.module.Connect(m.c, args)
406 | }
407 |
408 | if err != nil {
409 | *pzErr = mPrintf("%s", err.Error())
410 | return 0
411 | }
412 | vt := sqliteVTab{m, vTab}
413 | *pzErr = nil
414 | return C.uintptr_t(uintptr(newHandle(m.c, &vt)))
415 | }
416 |
417 | //export goVRelease
418 | func goVRelease(pVTab unsafe.Pointer, isDestroy C.int) *C.char {
419 | vt := lookupHandle(pVTab).(*sqliteVTab)
420 | var err error
421 | if isDestroy == 1 {
422 | err = vt.vTab.Destroy()
423 | } else {
424 | err = vt.vTab.Disconnect()
425 | }
426 | if err != nil {
427 | return mPrintf("%s", err.Error())
428 | }
429 | return nil
430 | }
431 |
432 | //export goVOpen
433 | func goVOpen(pVTab unsafe.Pointer, pzErr **C.char) C.uintptr_t {
434 | vt := lookupHandle(pVTab).(*sqliteVTab)
435 | vTabCursor, err := vt.vTab.Open()
436 | if err != nil {
437 | *pzErr = mPrintf("%s", err.Error())
438 | return 0
439 | }
440 | vtc := sqliteVTabCursor{vt, vTabCursor}
441 | *pzErr = nil
442 | return C.uintptr_t(uintptr(newHandle(vt.module.c, &vtc)))
443 | }
444 |
445 | //export goVBestIndex
446 | func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
447 | vt := lookupHandle(pVTab).(*sqliteVTab)
448 | info := (*C.sqlite3_index_info)(icp)
449 | csts := constraints(info)
450 | res, err := vt.vTab.BestIndex(csts, orderBys(info))
451 | if err != nil {
452 | return mPrintf("%s", err.Error())
453 | }
454 | if len(res.Used) != len(csts) {
455 | return mPrintf("Result.Used != expected value", "")
456 | }
457 |
458 | // Get a pointer to constraint_usage struct so we can update in place.
459 |
460 | slice := *(*[]C.struct_sqlite3_index_constraint_usage)(unsafe.Pointer(&reflect.SliceHeader{
461 | Data: uintptr(unsafe.Pointer(info.aConstraintUsage)),
462 | Len: int(info.nConstraint),
463 | Cap: int(info.nConstraint),
464 | }))
465 | index := 1
466 | for i := range slice {
467 | if res.Used[i] {
468 | slice[i].argvIndex = C.int(index)
469 | slice[i].omit = C.uchar(1)
470 | index++
471 | }
472 | }
473 |
474 | info.idxNum = C.int(res.IdxNum)
475 | info.idxStr = (*C.char)(C.sqlite3_malloc(C.int(len(res.IdxStr) + 1)))
476 | if info.idxStr == nil {
477 | // C.malloc and C.CString ordinarily do this for you. See https://golang.org/cmd/cgo/
478 | panic("out of memory")
479 | }
480 | info.needToFreeIdxStr = C.int(1)
481 |
482 | idxStr := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
483 | Data: uintptr(unsafe.Pointer(info.idxStr)),
484 | Len: len(res.IdxStr) + 1,
485 | Cap: len(res.IdxStr) + 1,
486 | }))
487 | copy(idxStr, res.IdxStr)
488 | idxStr[len(idxStr)-1] = 0 // null-terminated string
489 |
490 | if res.AlreadyOrdered {
491 | info.orderByConsumed = C.int(1)
492 | }
493 | info.estimatedCost = C.double(res.EstimatedCost)
494 | info.estimatedRows = C.sqlite3_int64(res.EstimatedRows)
495 |
496 | return nil
497 | }
498 |
499 | //export goVClose
500 | func goVClose(pCursor unsafe.Pointer) *C.char {
501 | vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
502 | err := vtc.vTabCursor.Close()
503 | if err != nil {
504 | return mPrintf("%s", err.Error())
505 | }
506 | return nil
507 | }
508 |
509 | //export goMDestroy
510 | func goMDestroy(pClientData unsafe.Pointer) {
511 | m := lookupHandle(pClientData).(*sqliteModule)
512 | m.module.DestroyModule()
513 | }
514 |
515 | //export goVFilter
516 | func goVFilter(pCursor unsafe.Pointer, idxNum C.int, idxName *C.char, argc C.int, argv **C.sqlite3_value) *C.char {
517 | vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
518 | args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
519 | vals := make([]interface{}, 0, argc)
520 | for _, v := range args {
521 | conv, err := callbackArgGeneric(v)
522 | if err != nil {
523 | return mPrintf("%s", err.Error())
524 | }
525 | vals = append(vals, conv.Interface())
526 | }
527 | err := vtc.vTabCursor.Filter(int(idxNum), C.GoString(idxName), vals)
528 | if err != nil {
529 | return mPrintf("%s", err.Error())
530 | }
531 | return nil
532 | }
533 |
534 | //export goVNext
535 | func goVNext(pCursor unsafe.Pointer) *C.char {
536 | vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
537 | err := vtc.vTabCursor.Next()
538 | if err != nil {
539 | return mPrintf("%s", err.Error())
540 | }
541 | return nil
542 | }
543 |
544 | //export goVEof
545 | func goVEof(pCursor unsafe.Pointer) C.int {
546 | vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
547 | err := vtc.vTabCursor.EOF()
548 | if err {
549 | return 1
550 | }
551 | return 0
552 | }
553 |
554 | //export goVColumn
555 | func goVColumn(pCursor, cp unsafe.Pointer, col C.int) *C.char {
556 | vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
557 | c := (*SQLiteContext)(cp)
558 | err := vtc.vTabCursor.Column(c, int(col))
559 | if err != nil {
560 | return mPrintf("%s", err.Error())
561 | }
562 | return nil
563 | }
564 |
565 | //export goVRowid
566 | func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
567 | vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
568 | rowid, err := vtc.vTabCursor.Rowid()
569 | if err != nil {
570 | return mPrintf("%s", err.Error())
571 | }
572 | *pRowid = C.sqlite3_int64(rowid)
573 | return nil
574 | }
575 |
576 | //export goVUpdate
577 | func goVUpdate(pVTab unsafe.Pointer, argc C.int, argv **C.sqlite3_value, pRowid *C.sqlite3_int64) *C.char {
578 | vt := lookupHandle(pVTab).(*sqliteVTab)
579 |
580 | var tname string
581 | if n, ok := vt.vTab.(interface {
582 | TableName() string
583 | }); ok {
584 | tname = n.TableName() + " "
585 | }
586 |
587 | err := fmt.Errorf("virtual %s table %sis read-only", vt.module.name, tname)
588 | if v, ok := vt.vTab.(VTabUpdater); ok {
589 | // convert argv
590 | args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
591 | vals := make([]interface{}, 0, argc)
592 | for _, v := range args {
593 | conv, err := callbackArgGeneric(v)
594 | if err != nil {
595 | return mPrintf("%s", err.Error())
596 | }
597 |
598 | // work around for SQLITE_NULL
599 | x := conv.Interface()
600 | if z, ok := x.([]byte); ok && z == nil {
601 | x = nil
602 | }
603 |
604 | vals = append(vals, x)
605 | }
606 |
607 | switch {
608 | case argc == 1:
609 | err = v.Delete(vals[0])
610 |
611 | case argc > 1 && vals[0] == nil:
612 | var id int64
613 | id, err = v.Insert(vals[1], vals[2:])
614 | if err == nil {
615 | *pRowid = C.sqlite3_int64(id)
616 | }
617 |
618 | case argc > 1:
619 | err = v.Update(vals[1], vals[2:])
620 | }
621 | }
622 |
623 | if err != nil {
624 | return mPrintf("%s", err.Error())
625 | }
626 |
627 | return nil
628 | }
629 |
630 | // Module is a "virtual table module", it defines the implementation of a
631 | // virtual tables. See: http://sqlite.org/c3ref/module.html
632 | type Module interface {
633 | // http://sqlite.org/vtab.html#xcreate
634 | Create(c *SQLiteConn, args []string) (VTab, error)
635 | // http://sqlite.org/vtab.html#xconnect
636 | Connect(c *SQLiteConn, args []string) (VTab, error)
637 | // http://sqlite.org/c3ref/create_module.html
638 | DestroyModule()
639 | }
640 |
641 | // EponymousOnlyModule is a "virtual table module" (as above), but
642 | // for defining "eponymous only" virtual tables See: https://sqlite.org/vtab.html#eponymous_only_virtual_tables
643 | type EponymousOnlyModule interface {
644 | Module
645 | EponymousOnlyModule()
646 | }
647 |
648 | // VTab describes a particular instance of the virtual table.
649 | // See: http://sqlite.org/c3ref/vtab.html
650 | type VTab interface {
651 | // http://sqlite.org/vtab.html#xbestindex
652 | BestIndex([]InfoConstraint, []InfoOrderBy) (*IndexResult, error)
653 | // http://sqlite.org/vtab.html#xdisconnect
654 | Disconnect() error
655 | // http://sqlite.org/vtab.html#sqlite3_module.xDestroy
656 | Destroy() error
657 | // http://sqlite.org/vtab.html#xopen
658 | Open() (VTabCursor, error)
659 | }
660 |
661 | // VTabUpdater is a type that allows a VTab to be inserted, updated, or
662 | // deleted.
663 | // See: https://sqlite.org/vtab.html#xupdate
664 | type VTabUpdater interface {
665 | Delete(interface{}) error
666 | Insert(interface{}, []interface{}) (int64, error)
667 | Update(interface{}, []interface{}) error
668 | }
669 |
670 | // VTabCursor describes cursors that point into the virtual table and are used
671 | // to loop through the virtual table. See: http://sqlite.org/c3ref/vtab_cursor.html
672 | type VTabCursor interface {
673 | // http://sqlite.org/vtab.html#xclose
674 | Close() error
675 | // http://sqlite.org/vtab.html#xfilter
676 | Filter(idxNum int, idxStr string, vals []interface{}) error
677 | // http://sqlite.org/vtab.html#xnext
678 | Next() error
679 | // http://sqlite.org/vtab.html#xeof
680 | EOF() bool
681 | // http://sqlite.org/vtab.html#xcolumn
682 | Column(c *SQLiteContext, col int) error
683 | // http://sqlite.org/vtab.html#xrowid
684 | Rowid() (int64, error)
685 | }
686 |
687 | // DeclareVTab declares the Schema of a virtual table.
688 | // See: http://sqlite.org/c3ref/declare_vtab.html
689 | func (c *SQLiteConn) DeclareVTab(sql string) error {
690 | zSQL := C.CString(sql)
691 | defer C.free(unsafe.Pointer(zSQL))
692 | rv := C.sqlite3_declare_vtab(c.db, zSQL)
693 | if rv != C.SQLITE_OK {
694 | return c.lastError()
695 | }
696 | return nil
697 | }
698 |
699 | // CreateModule registers a virtual table implementation.
700 | // See: http://sqlite.org/c3ref/create_module.html
701 | func (c *SQLiteConn) CreateModule(moduleName string, module Module) error {
702 | mname := C.CString(moduleName)
703 | defer C.free(unsafe.Pointer(mname))
704 | udm := sqliteModule{c, moduleName, module}
705 | switch module.(type) {
706 | case EponymousOnlyModule:
707 | rv := C._sqlite3_create_module_eponymous_only(c.db, mname, C.uintptr_t(uintptr(newHandle(c, &udm))))
708 | if rv != C.SQLITE_OK {
709 | return c.lastError()
710 | }
711 | return nil
712 | case Module:
713 | rv := C._sqlite3_create_module(c.db, mname, C.uintptr_t(uintptr(newHandle(c, &udm))))
714 | if rv != C.SQLITE_OK {
715 | return c.lastError()
716 | }
717 | return nil
718 | }
719 | return nil
720 | }
721 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_other.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build !windows
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo CFLAGS: -I.
12 | #cgo linux LDFLAGS: -ldl
13 | #cgo linux,ppc LDFLAGS: -lpthread
14 | #cgo linux,ppc64 LDFLAGS: -lpthread
15 | #cgo linux,ppc64le LDFLAGS: -lpthread
16 | */
17 | import "C"
18 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_solaris.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build solaris
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo CFLAGS: -D__EXTENSIONS__=1
12 | #cgo LDFLAGS: -lc
13 | */
14 | import "C"
15 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build sqlite_trace trace
7 |
8 | package sqlite3
9 |
10 | /*
11 | #ifndef USE_LIBSQLITE3
12 | #include "sqlite3-binding.h"
13 | #else
14 | #include
15 | #endif
16 | #include
17 |
18 | int traceCallbackTrampoline(unsigned int traceEventCode, void *ctx, void *p, void *x);
19 | */
20 | import "C"
21 |
22 | import (
23 | "fmt"
24 | "strings"
25 | "sync"
26 | "unsafe"
27 | )
28 |
29 | // Trace... constants identify the possible events causing callback invocation.
30 | // Values are same as the corresponding SQLite Trace Event Codes.
31 | const (
32 | TraceStmt = uint32(C.SQLITE_TRACE_STMT)
33 | TraceProfile = uint32(C.SQLITE_TRACE_PROFILE)
34 | TraceRow = uint32(C.SQLITE_TRACE_ROW)
35 | TraceClose = uint32(C.SQLITE_TRACE_CLOSE)
36 | )
37 |
38 | type TraceInfo struct {
39 | // Pack together the shorter fields, to keep the struct smaller.
40 | // On a 64-bit machine there would be padding
41 | // between EventCode and ConnHandle; having AutoCommit here is "free":
42 | EventCode uint32
43 | AutoCommit bool
44 | ConnHandle uintptr
45 |
46 | // Usually filled, unless EventCode = TraceClose = SQLITE_TRACE_CLOSE:
47 | // identifier for a prepared statement:
48 | StmtHandle uintptr
49 |
50 | // Two strings filled when EventCode = TraceStmt = SQLITE_TRACE_STMT:
51 | // (1) either the unexpanded SQL text of the prepared statement, or
52 | // an SQL comment that indicates the invocation of a trigger;
53 | // (2) expanded SQL, if requested and if (1) is not an SQL comment.
54 | StmtOrTrigger string
55 | ExpandedSQL string // only if requested (TraceConfig.WantExpandedSQL = true)
56 |
57 | // filled when EventCode = TraceProfile = SQLITE_TRACE_PROFILE:
58 | // estimated number of nanoseconds that the prepared statement took to run:
59 | RunTimeNanosec int64
60 |
61 | DBError Error
62 | }
63 |
64 | // TraceUserCallback gives the signature for a trace function
65 | // provided by the user (Go application programmer).
66 | // SQLite 3.14 documentation (as of September 2, 2016)
67 | // for SQL Trace Hook = sqlite3_trace_v2():
68 | // The integer return value from the callback is currently ignored,
69 | // though this may change in future releases. Callback implementations
70 | // should return zero to ensure future compatibility.
71 | type TraceUserCallback func(TraceInfo) int
72 |
73 | type TraceConfig struct {
74 | Callback TraceUserCallback
75 | EventMask uint32
76 | WantExpandedSQL bool
77 | }
78 |
79 | func fillDBError(dbErr *Error, db *C.sqlite3) {
80 | // See SQLiteConn.lastError(), in file 'sqlite3.go' at the time of writing (Sept 5, 2016)
81 | dbErr.Code = ErrNo(C.sqlite3_errcode(db))
82 | dbErr.ExtendedCode = ErrNoExtended(C.sqlite3_extended_errcode(db))
83 | dbErr.err = C.GoString(C.sqlite3_errmsg(db))
84 | }
85 |
86 | func fillExpandedSQL(info *TraceInfo, db *C.sqlite3, pStmt unsafe.Pointer) {
87 | if pStmt == nil {
88 | panic("No SQLite statement pointer in P arg of trace_v2 callback")
89 | }
90 |
91 | expSQLiteCStr := C.sqlite3_expanded_sql((*C.sqlite3_stmt)(pStmt))
92 | defer C.sqlite3_free(unsafe.Pointer(expSQLiteCStr))
93 | if expSQLiteCStr == nil {
94 | fillDBError(&info.DBError, db)
95 | return
96 | }
97 | info.ExpandedSQL = C.GoString(expSQLiteCStr)
98 | }
99 |
100 | //export traceCallbackTrampoline
101 | func traceCallbackTrampoline(
102 | traceEventCode C.uint,
103 | // Parameter named 'C' in SQLite docs = Context given at registration:
104 | ctx unsafe.Pointer,
105 | // Parameter named 'P' in SQLite docs (Primary event data?):
106 | p unsafe.Pointer,
107 | // Parameter named 'X' in SQLite docs (eXtra event data?):
108 | xValue unsafe.Pointer) C.int {
109 |
110 | eventCode := uint32(traceEventCode)
111 |
112 | if ctx == nil {
113 | panic(fmt.Sprintf("No context (ev 0x%x)", traceEventCode))
114 | }
115 |
116 | contextDB := (*C.sqlite3)(ctx)
117 | connHandle := uintptr(ctx)
118 |
119 | var traceConf TraceConfig
120 | var found bool
121 | if eventCode == TraceClose {
122 | // clean up traceMap: 'pop' means get and delete
123 | traceConf, found = popTraceMapping(connHandle)
124 | } else {
125 | traceConf, found = lookupTraceMapping(connHandle)
126 | }
127 |
128 | if !found {
129 | panic(fmt.Sprintf("Mapping not found for handle 0x%x (ev 0x%x)",
130 | connHandle, eventCode))
131 | }
132 |
133 | var info TraceInfo
134 |
135 | info.EventCode = eventCode
136 | info.AutoCommit = (int(C.sqlite3_get_autocommit(contextDB)) != 0)
137 | info.ConnHandle = connHandle
138 |
139 | switch eventCode {
140 | case TraceStmt:
141 | info.StmtHandle = uintptr(p)
142 |
143 | var xStr string
144 | if xValue != nil {
145 | xStr = C.GoString((*C.char)(xValue))
146 | }
147 | info.StmtOrTrigger = xStr
148 | if !strings.HasPrefix(xStr, "--") {
149 | // Not SQL comment, therefore the current event
150 | // is not related to a trigger.
151 | // The user might want to receive the expanded SQL;
152 | // let's check:
153 | if traceConf.WantExpandedSQL {
154 | fillExpandedSQL(&info, contextDB, p)
155 | }
156 | }
157 |
158 | case TraceProfile:
159 | info.StmtHandle = uintptr(p)
160 |
161 | if xValue == nil {
162 | panic("NULL pointer in X arg of trace_v2 callback for SQLITE_TRACE_PROFILE event")
163 | }
164 |
165 | info.RunTimeNanosec = *(*int64)(xValue)
166 |
167 | // sample the error //TODO: is it safe? is it useful?
168 | fillDBError(&info.DBError, contextDB)
169 |
170 | case TraceRow:
171 | info.StmtHandle = uintptr(p)
172 |
173 | case TraceClose:
174 | handle := uintptr(p)
175 | if handle != info.ConnHandle {
176 | panic(fmt.Sprintf("Different conn handle 0x%x (expected 0x%x) in SQLITE_TRACE_CLOSE event.",
177 | handle, info.ConnHandle))
178 | }
179 |
180 | default:
181 | // Pass unsupported events to the user callback (if configured);
182 | // let the user callback decide whether to panic or ignore them.
183 | }
184 |
185 | // Do not execute user callback when the event was not requested by user!
186 | // Remember that the Close event is always selected when
187 | // registering this callback trampoline with SQLite --- for cleanup.
188 | // In the future there may be more events forced to "selected" in SQLite
189 | // for the driver's needs.
190 | if traceConf.EventMask&eventCode == 0 {
191 | return 0
192 | }
193 |
194 | r := 0
195 | if traceConf.Callback != nil {
196 | r = traceConf.Callback(info)
197 | }
198 | return C.int(r)
199 | }
200 |
201 | type traceMapEntry struct {
202 | config TraceConfig
203 | }
204 |
205 | var traceMapLock sync.Mutex
206 | var traceMap = make(map[uintptr]traceMapEntry)
207 |
208 | func addTraceMapping(connHandle uintptr, traceConf TraceConfig) {
209 | traceMapLock.Lock()
210 | defer traceMapLock.Unlock()
211 |
212 | oldEntryCopy, found := traceMap[connHandle]
213 | if found {
214 | panic(fmt.Sprintf("Adding trace config %v: handle 0x%x already registered (%v).",
215 | traceConf, connHandle, oldEntryCopy.config))
216 | }
217 | traceMap[connHandle] = traceMapEntry{config: traceConf}
218 | }
219 |
220 | func lookupTraceMapping(connHandle uintptr) (TraceConfig, bool) {
221 | traceMapLock.Lock()
222 | defer traceMapLock.Unlock()
223 |
224 | entryCopy, found := traceMap[connHandle]
225 | return entryCopy.config, found
226 | }
227 |
228 | // 'pop' = get and delete from map before returning the value to the caller
229 | func popTraceMapping(connHandle uintptr) (TraceConfig, bool) {
230 | traceMapLock.Lock()
231 | defer traceMapLock.Unlock()
232 |
233 | entryCopy, found := traceMap[connHandle]
234 | if found {
235 | delete(traceMap, connHandle)
236 | }
237 | return entryCopy.config, found
238 | }
239 |
240 | // SetTrace installs or removes the trace callback for the given database connection.
241 | // It's not named 'RegisterTrace' because only one callback can be kept and called.
242 | // Calling SetTrace a second time on same database connection
243 | // overrides (cancels) any prior callback and all its settings:
244 | // event mask, etc.
245 | func (c *SQLiteConn) SetTrace(requested *TraceConfig) error {
246 | connHandle := uintptr(unsafe.Pointer(c.db))
247 |
248 | _, _ = popTraceMapping(connHandle)
249 |
250 | if requested == nil {
251 | // The traceMap entry was deleted already by popTraceMapping():
252 | // can disable all events now, no need to watch for TraceClose.
253 | err := c.setSQLiteTrace(0)
254 | return err
255 | }
256 |
257 | reqCopy := *requested
258 |
259 | // Disable potentially expensive operations
260 | // if their result will not be used. We are doing this
261 | // just in case the caller provided nonsensical input.
262 | if reqCopy.EventMask&TraceStmt == 0 {
263 | reqCopy.WantExpandedSQL = false
264 | }
265 |
266 | addTraceMapping(connHandle, reqCopy)
267 |
268 | // The callback trampoline function does cleanup on Close event,
269 | // regardless of the presence or absence of the user callback.
270 | // Therefore it needs the Close event to be selected:
271 | actualEventMask := uint(reqCopy.EventMask | TraceClose)
272 | err := c.setSQLiteTrace(actualEventMask)
273 | return err
274 | }
275 |
276 | func (c *SQLiteConn) setSQLiteTrace(sqliteEventMask uint) error {
277 | rv := C.sqlite3_trace_v2(c.db,
278 | C.uint(sqliteEventMask),
279 | (*[0]byte)(unsafe.Pointer(C.traceCallbackTrampoline)),
280 | unsafe.Pointer(c.db)) // Fourth arg is same as first: we are
281 | // passing the database connection handle as callback context.
282 |
283 | if rv != C.SQLITE_OK {
284 | return c.lastError()
285 | }
286 | return nil
287 | }
288 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_type.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | // Use of this source code is governed by an MIT-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package sqlite3
6 |
7 | /*
8 | #ifndef USE_LIBSQLITE3
9 | #include "sqlite3-binding.h"
10 | #else
11 | #include
12 | #endif
13 | */
14 | import "C"
15 | import (
16 | "database/sql"
17 | "reflect"
18 | "strings"
19 | )
20 |
21 | // ColumnTypeDatabaseTypeName implement RowsColumnTypeDatabaseTypeName.
22 | func (rc *SQLiteRows) ColumnTypeDatabaseTypeName(i int) string {
23 | return C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))
24 | }
25 |
26 | /*
27 | func (rc *SQLiteRows) ColumnTypeLength(index int) (length int64, ok bool) {
28 | return 0, false
29 | }
30 |
31 | func (rc *SQLiteRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
32 | return 0, 0, false
33 | }
34 | */
35 |
36 | // ColumnTypeNullable implement RowsColumnTypeNullable.
37 | func (rc *SQLiteRows) ColumnTypeNullable(i int) (nullable, ok bool) {
38 | return true, true
39 | }
40 |
41 | // ColumnTypeScanType implement RowsColumnTypeScanType.
42 | func (rc *SQLiteRows) ColumnTypeScanType(i int) reflect.Type {
43 | //ct := C.sqlite3_column_type(rc.s.s, C.int(i)) // Always returns 5
44 | return scanType(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))))
45 | }
46 |
47 | const (
48 | SQLITE_INTEGER = iota
49 | SQLITE_TEXT
50 | SQLITE_BLOB
51 | SQLITE_REAL
52 | SQLITE_NUMERIC
53 | SQLITE_TIME
54 | SQLITE_BOOL
55 | SQLITE_NULL
56 | )
57 |
58 | func scanType(cdt string) reflect.Type {
59 | t := strings.ToUpper(cdt)
60 | i := databaseTypeConvSqlite(t)
61 | switch i {
62 | case SQLITE_INTEGER:
63 | return reflect.TypeOf(sql.NullInt64{})
64 | case SQLITE_TEXT:
65 | return reflect.TypeOf(sql.NullString{})
66 | case SQLITE_BLOB:
67 | return reflect.TypeOf(sql.RawBytes{})
68 | case SQLITE_REAL:
69 | return reflect.TypeOf(sql.NullFloat64{})
70 | case SQLITE_NUMERIC:
71 | return reflect.TypeOf(sql.NullFloat64{})
72 | case SQLITE_BOOL:
73 | return reflect.TypeOf(sql.NullBool{})
74 | case SQLITE_TIME:
75 | return reflect.TypeOf(sql.NullTime{})
76 | }
77 | return reflect.TypeOf(new(interface{}))
78 | }
79 |
80 | func databaseTypeConvSqlite(t string) int {
81 | if strings.Contains(t, "INT") {
82 | return SQLITE_INTEGER
83 | }
84 | if t == "CLOB" || t == "TEXT" ||
85 | strings.Contains(t, "CHAR") {
86 | return SQLITE_TEXT
87 | }
88 | if t == "BLOB" {
89 | return SQLITE_BLOB
90 | }
91 | if t == "REAL" || t == "FLOAT" ||
92 | strings.Contains(t, "DOUBLE") {
93 | return SQLITE_REAL
94 | }
95 | if t == "DATE" || t == "DATETIME" ||
96 | t == "TIMESTAMP" {
97 | return SQLITE_TIME
98 | }
99 | if t == "NUMERIC" ||
100 | strings.Contains(t, "DECIMAL") {
101 | return SQLITE_NUMERIC
102 | }
103 | if t == "BOOLEAN" {
104 | return SQLITE_BOOL
105 | }
106 |
107 | return SQLITE_NULL
108 | }
109 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_usleep_windows.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2018 G.J.R. Timmer .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build cgo
7 |
8 | package sqlite3
9 |
10 | // usleep is a function available on *nix based systems.
11 | // This function is not present in Windows.
12 | // Windows has a sleep function but this works with seconds
13 | // and not with microseconds as usleep.
14 | //
15 | // This code should improve performance on windows because
16 | // without the presence of usleep SQLite waits 1 second.
17 | //
18 | // Source: https://github.com/php/php-src/blob/PHP-5.0/win32/time.c
19 | // License: https://github.com/php/php-src/blob/PHP-5.0/LICENSE
20 | // Details: https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
21 |
22 | /*
23 | #include
24 |
25 | void usleep(__int64 usec)
26 | {
27 | HANDLE timer;
28 | LARGE_INTEGER ft;
29 |
30 | // Convert to 100 nanosecond interval, negative value indicates relative time
31 | ft.QuadPart = -(10*usec);
32 |
33 | timer = CreateWaitableTimer(NULL, TRUE, NULL);
34 | SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
35 | WaitForSingleObject(timer, INFINITE);
36 | CloseHandle(timer);
37 | }
38 | */
39 | import "C"
40 |
41 | // EOF
42 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build windows
7 |
8 | package sqlite3
9 |
10 | /*
11 | #cgo CFLAGS: -I.
12 | #cgo CFLAGS: -fno-stack-check
13 | #cgo CFLAGS: -fno-stack-protector
14 | #cgo CFLAGS: -mno-stack-arg-probe
15 | #cgo LDFLAGS: -lmingwex -lmingw32
16 | #cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T
17 | */
18 | import "C"
19 |
--------------------------------------------------------------------------------
/vendor/github.com/mattn/go-sqlite3/static_mock.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2019 Yasuhiro Matsumoto .
2 | //
3 | // Use of this source code is governed by an MIT-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build !cgo
7 |
8 | package sqlite3
9 |
10 | import (
11 | "database/sql"
12 | "database/sql/driver"
13 | "errors"
14 | )
15 |
16 | var errorMsg = errors.New("Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub")
17 |
18 | func init() {
19 | sql.Register("sqlite3", &SQLiteDriver{})
20 | }
21 |
22 | type (
23 | SQLiteDriver struct {
24 | Extensions []string
25 | ConnectHook func(*SQLiteConn) error
26 | }
27 | SQLiteConn struct{}
28 | )
29 |
30 | func (SQLiteDriver) Open(s string) (driver.Conn, error) { return nil, errorMsg }
31 | func (c *SQLiteConn) RegisterAggregator(string, interface{}, bool) error { return errorMsg }
32 | func (c *SQLiteConn) RegisterAuthorizer(func(int, string, string, string) int) {}
33 | func (c *SQLiteConn) RegisterCollation(string, func(string, string) int) error { return errorMsg }
34 | func (c *SQLiteConn) RegisterCommitHook(func() int) {}
35 | func (c *SQLiteConn) RegisterFunc(string, interface{}, bool) error { return errorMsg }
36 | func (c *SQLiteConn) RegisterRollbackHook(func()) {}
37 | func (c *SQLiteConn) RegisterUpdateHook(func(int, string, string, int64)) {}
38 |
--------------------------------------------------------------------------------
/vendor/modules.txt:
--------------------------------------------------------------------------------
1 | # github.com/mattn/go-sqlite3 v1.14.10
2 | ## explicit
3 | github.com/mattn/go-sqlite3
4 |
--------------------------------------------------------------------------------
/vm-harness/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "log"
7 | "net"
8 | "os"
9 | "os/exec"
10 | "strings"
11 | "time"
12 | )
13 |
14 | func main() {
15 | qemucmd := exec.Command("/usr/local/bin/qemu-system-x86_64",
16 | "-m", "192",
17 | "-drive", "file=98.qcow2,id=disk,cache=unsafe",
18 | "-net", "nic,model=ne2k_isa",
19 | "-net", "user,hostfwd=tcp:127.0.0.1:5555-:8443",
20 |
21 | "-drive", "file=0.iso,index=3,media=cdrom",
22 | "-drive", "file=1.iso,index=1,media=cdrom",
23 | "-drive", "file=2.iso,index=2,media=cdrom",
24 |
25 | "-vnc", "127.0.0.1:0",
26 | "-vga", "cirrus",
27 | "-serial", "stdio") // to read off the windows 98 reporter
28 |
29 | qemucmd.Stderr = os.Stderr
30 | serial, err := qemucmd.StdoutPipe()
31 | if err != nil {
32 | log.Fatalf("!!! %s", err.Error())
33 | }
34 |
35 | c, err := net.Dial("unix", "/var/run/collectd.socket")
36 | if err != nil {
37 | log.Fatalf("Cannot connect to collectd! %s", err.Error())
38 | }
39 |
40 | go func() {
41 | err := qemucmd.Run()
42 | if err != nil {
43 | log.Fatalf("!!! %s", err.Error())
44 | }
45 | }()
46 |
47 | time.Sleep(time.Second * 5)
48 |
49 | go func() {
50 | for {
51 | b := make([]byte, 1000)
52 | n, err := c.Read(b)
53 | if err != nil {
54 | return
55 | }
56 | fmt.Print(string(b[:n]))
57 | }
58 | }()
59 |
60 | reader := bufio.NewReader(serial)
61 | for {
62 | ln, _, err := reader.ReadLine()
63 | if err != nil {
64 | return
65 | }
66 | c.Write([]byte(strings.Replace(string(ln), " N: ", " N:", 1) + "\n"))
67 | }
68 | }
69 |
--------------------------------------------------------------------------------