Merge remote-tracking branch 'origin/go-rewrite' into go-rewrite

This commit is contained in:
Bora M. Alper 2017-08-21 17:17:31 +03:00
commit b5ee1029e2

View File

@ -5,6 +5,7 @@ import (
"database/sql" "database/sql"
"net/url" "net/url"
_ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"go.uber.org/zap" "go.uber.org/zap"
@ -15,22 +16,20 @@ import (
"bytes" "bytes"
) )
type engineType uint8 type engineType uint8
const ( const (
SQLITE engineType = 0 SQLITE engineType = 0
POSTGRESQL = 1 POSTGRESQL = 1
MYSQL = 2
) )
type Database struct { type Database struct {
database *sql.DB database *sql.DB
engine engineType engine engineType
newTorrents []bittorrent.Metadata newTorrents [] bittorrent.Metadata
} }
// NewDatabase creates a new Database. // NewDatabase creates a new Database.
// //
// url either starts with "sqlite:" or "postgresql:" // url either starts with "sqlite:" or "postgresql:"
@ -55,6 +54,10 @@ func NewDatabase(rawurl string) (*Database, error) {
db.engine = POSTGRESQL db.engine = POSTGRESQL
db.database, err = sql.Open("postgresql", rawurl) db.database, err = sql.Open("postgresql", rawurl)
case "mysql":
db.engine = MYSQL
db.database, err = sql.Open("mysql", rawurl)
default: default:
return nil, fmt.Errorf("unknown URI scheme (or malformed URI)!") return nil, fmt.Errorf("unknown URI scheme (or malformed URI)!")
} }
@ -124,7 +127,7 @@ func (db *Database) AddNewTorrent(torrent bittorrent.Metadata) error {
func (db *Database) commitNewTorrents() error { func (db *Database) commitNewTorrents() error {
tx, err := db.database.Begin() tx, err := db.database.Begin()
if err != nil { if err != nil {
return fmt.Errorf("sql.DB.Begin()! %s", err.Error()) return fmt.Errorf("sql.DB.Begin()! %s", err.Error())
} }
@ -175,13 +178,11 @@ func (db *Database) commitNewTorrents() error {
return nil return nil
} }
func (db *Database) Close() { func (db *Database) Close() {
// Be careful to not to get into an infinite loop. =) // Be careful to not to get into an infinite loop. =)
db.database.Close() db.database.Close()
} }
func (db *Database) setupDatabase() error { func (db *Database) setupDatabase() error {
switch db.engine { switch db.engine {
case SQLITE: case SQLITE:
@ -190,6 +191,9 @@ func (db *Database) setupDatabase() error {
case POSTGRESQL: case POSTGRESQL:
zap.L().Fatal("setupDatabase() is not implemented for PostgreSQL yet!") zap.L().Fatal("setupDatabase() is not implemented for PostgreSQL yet!")
case MYSQL:
return setupMySQLDatabase(db.database)
default: default:
zap.L().Sugar().Fatalf("Unknown database engine value %d! (programmer error)", db.engine) zap.L().Sugar().Fatalf("Unknown database engine value %d! (programmer error)", db.engine)
} }
@ -197,7 +201,6 @@ func (db *Database) setupDatabase() error {
return nil return nil
} }
func setupSqliteDatabase(database *sql.DB) error { func setupSqliteDatabase(database *sql.DB) error {
// Enable Write-Ahead Logging for SQLite as "WAL provides more concurrency as readers do not // Enable Write-Ahead Logging for SQLite as "WAL provides more concurrency as readers do not
// block writers and a writer does not block readers. Reading and writing can proceed // block writers and a writer does not block readers. Reading and writing can proceed
@ -247,3 +250,36 @@ func setupSqliteDatabase(database *sql.DB) error {
return nil return nil
} }
func setupMySQLDatabase(database *sql.DB) error {
// Set strict mode to prevent silent truncation
_, err := database.Exec(`SET SESSION SQL_MODE = 'STRICT_ALL_TABLES';`)
if err != nil {
return err
}
_, err = database.Exec(
`CREATE TABLE IF NOT EXISTS torrents ("
id INTEGER PRIMARY KEY AUTO_INCREMENT,
info_hash BINARY(20) NOT NULL UNIQUE,
name VARCHAR(1024) NOT NULL,
total_size BIGINT UNSIGNED NOT NULL,
discovered_on INTEGER UNSIGNED NOT NULL
);
ALTER TABLE torrents ADD INDEX info_hash_index (info_hash);
CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
torrent_id INTEGER REFERENCES torrents (id) ON DELETE CASCADE ON UPDATE RESTRICT,
size BIGINT NOT NULL,
path TEXT NOT NULL
);`,
)
if err != nil {
return err
}
return nil
}