|
- /*
- Copyright © 2019 Devan Carpenter <mail@dvn.me>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- // functions for database actions
- package db
-
- import (
- "fmt"
- "time"
-
- "boxen/config"
- "github.com/bvinc/go-sqlite-lite/sqlite3"
- )
-
- func DBinit() error {
- // Open DB file. File will be created if non-existent.
- conn, err := sqlite3.Open(config.ConfigPath + "boxen.db")
- if err != nil {
- return fmt.Errorf("failed to open database: %v", err)
- }
- defer conn.Close()
-
- // Busy timeout
- conn.BusyTimeout(5 * time.Second)
-
- // Create a new table to store device info, if it doesn't already exist.
- err = conn.Exec(`CREATE TABLE if not exists devices(device_name TEXT, device_ego TEXT, service_name TEXT, service_record TEXT, owner INTEGER, UNIQUE(device_name, device_ego, service_name, service_record, owner))`)
- if err != nil {
- return fmt.Errorf("failed to create database table: %v", err)
- }
-
- // Create a new table to store device info, if it doesn't already exist.
- err = conn.Exec(`CREATE TABLE if not exists friends(device_name TEXT, friend_name TEXT, friend_ego TEXT, UNIQUE(ego))`)
- if err != nil {
- return fmt.Errorf("failed to create database table: %v", err)
- }
-
- return nil
- }
-
- func InsertDevice(device_name string, device_ego string, service_name string, service_record string, owner int) error {
- // Open DB file. File will be created if non-existent.
- conn, err := sqlite3.Open(config.ConfigPath + "boxen.db")
- if err != nil {
- return fmt.Errorf("failed to open database: %v", err)
- }
- defer conn.Close()
-
- // Busy timeout
- conn.BusyTimeout(5 * time.Second)
-
- err = conn.WithTx(func() error {
- return insertDevices(conn, device_name, device_ego, service_name, service_record, owner)
- })
- if err != nil {
- return fmt.Errorf("failed to insert device: %v", err)
- }
-
- return nil
- }
-
- func insertDevices(conn *sqlite3.Conn, device_name string, device_ego string, service_name string, service_record string, owner int) error {
- // Create a prepared statement
- stmt, err := conn.Prepare(`INSERT OR IGNORE INTO devices(device_name, device_ego, service_name, service_record, owner) VALUES (?, ?, ?, ?, ?)`)
- if err != nil {
- return fmt.Errorf("failed to prepare to insert to students table: %v", err)
- }
- defer stmt.Close()
-
- // Even more convenient, Exec will call Bind, Step as many times as needed
- // and always Reset the statement
- if err = stmt.Exec(device_name, device_ego, service_name, service_record, owner); err != nil {
- return fmt.Errorf("failed to insert student: %v", err)
- }
-
- return nil
- }
-
- func queryStudents(conn *sqlite3.Conn) error {
- // Prepare can prepare a statement and optionally also bind arguments
- stmt, err := conn.Prepare(`SELECT * FROM devices`)
- if err != nil {
- return fmt.Errorf("failed to select from students table: %v", err)
- }
- defer stmt.Close()
-
- for {
- hasRow, err := stmt.Step()
- if err != nil {
- return fmt.Errorf("step failed while querying students: %v", err)
- }
- if !hasRow {
- break
- }
-
- // Use Scan to access column data from a row
- var name string
- var services string
- var friends string
- var owner int
- err = stmt.Scan(&name, &services, &friends, &owner)
- if err != nil {
- return fmt.Errorf("scan failed while querying students: %v", err)
- }
-
- fmt.Println("name:", name, "services:", services, "friends:", friends, "owner:", owner)
- }
-
- return nil
- }
|