github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/pkg/sorted/sqlite/dbschema.go (about) 1 /* 2 Copyright 2012 The Camlistore Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package sqlite 18 19 import ( 20 "bytes" 21 "database/sql" 22 "fmt" 23 "log" 24 "os" 25 "os/exec" 26 "path/filepath" 27 "runtime" 28 "strings" 29 ) 30 31 const requiredSchemaVersion = 1 32 33 func SchemaVersion() int { 34 return requiredSchemaVersion 35 } 36 37 func SQLCreateTables() []string { 38 return []string{ 39 `CREATE TABLE rows ( 40 k VARCHAR(255) NOT NULL PRIMARY KEY, 41 v VARCHAR(255))`, 42 43 `CREATE TABLE meta ( 44 metakey VARCHAR(255) NOT NULL PRIMARY KEY, 45 value VARCHAR(255) NOT NULL)`, 46 } 47 } 48 49 // IsWALCapable checks if the installed sqlite3 library can 50 // use Write-Ahead Logging (i.e version >= 3.7.0) 51 func IsWALCapable() bool { 52 // TODO(mpl): alternative to make it work on windows 53 cmdPath, err := exec.LookPath("pkg-config") 54 if err != nil { 55 log.Printf("Could not find pkg-config to check sqlite3 lib version: %v", err) 56 return false 57 } 58 var stderr bytes.Buffer 59 cmd := exec.Command(cmdPath, "--modversion", "sqlite3") 60 cmd.Stderr = &stderr 61 if runtime.GOOS == "darwin" && os.Getenv("PKG_CONFIG_PATH") == "" { 62 matches, err := filepath.Glob("/usr/local/Cellar/sqlite/*/lib/pkgconfig/sqlite3.pc") 63 if err == nil && len(matches) > 0 { 64 cmd.Env = append(os.Environ(), "PKG_CONFIG_PATH="+filepath.Dir(matches[0])) 65 } 66 } 67 68 out, err := cmd.Output() 69 if err != nil { 70 log.Printf("Could not check sqlite3 version: %v\n", stderr.String()) 71 return false 72 } 73 version := strings.TrimRight(string(out), "\n") 74 return version >= "3.7.0" 75 } 76 77 // EnableWAL returns the statement to enable Write-Ahead Logging, 78 // which improves SQLite concurrency. 79 // Requires SQLite >= 3.7.0 80 func EnableWAL() string { 81 return "PRAGMA journal_mode = WAL" 82 } 83 84 // initDB creates a new sqlite database based on the file at path. 85 func initDB(path string) error { 86 db, err := sql.Open("sqlite3", path) 87 if err != nil { 88 return err 89 } 90 defer db.Close() 91 for _, tableSql := range SQLCreateTables() { 92 if _, err := db.Exec(tableSql); err != nil { 93 return err 94 } 95 } 96 if IsWALCapable() { 97 if _, err := db.Exec(EnableWAL()); err != nil { 98 return err 99 } 100 } else { 101 log.Print("WARNING: An SQLite DB without Write Ahead Logging will most likely fail. See http://camlistore.org/issues/114") 102 } 103 _, err = db.Exec(fmt.Sprintf(`REPLACE INTO meta VALUES ('version', '%d')`, SchemaVersion())) 104 return err 105 }