diff --git a/store/datastore/files.go b/store/datastore/files.go index 3aadfc6e..108ebcfa 100644 --- a/store/datastore/files.go +++ b/store/datastore/files.go @@ -12,21 +12,21 @@ import ( ) func (db *datastore) FileList(build *model.Build) ([]*model.File, error) { - stmt := sql.Lookup(sql.DriverMysql, "files-find-build") + stmt := sql.Lookup(db.driver, "files-find-build") list := []*model.File{} err := meddler.QueryAll(db, &list, stmt, build.ID) return list, err } func (db *datastore) FileFind(proc *model.Proc, name string) (*model.File, error) { - stmt := sql.Lookup(sql.DriverMysql, "files-find-proc-name") + stmt := sql.Lookup(db.driver, "files-find-proc-name") file := new(model.File) err := meddler.QueryRow(db, file, stmt, proc.ID, name) return file, err } func (db *datastore) FileRead(proc *model.Proc, name string) (io.ReadCloser, error) { - stmt := sql.Lookup(sql.DriverMysql, "files-find-proc-name-data") + stmt := sql.Lookup(db.driver, "files-find-proc-name-data") file := new(fileData) err := meddler.QueryRow(db, file, stmt, proc.ID, name) buf := bytes.NewBuffer(file.Data) diff --git a/store/datastore/files_test.go b/store/datastore/files_test.go index 2d5c7745..35752035 100644 --- a/store/datastore/files_test.go +++ b/store/datastore/files_test.go @@ -9,10 +9,9 @@ import ( ) func TestFileFind(t *testing.T) { - db := openTest() - defer db.Close() + s := newTest() + defer s.Close() - s := From(db) if err := s.FileCreate( &model.File{ BuildID: 2, @@ -63,10 +62,9 @@ func TestFileFind(t *testing.T) { } func TestFileList(t *testing.T) { - db := openTest() - defer db.Close() + s := newTest() + defer s.Close() - s := From(db) s.FileCreate( &model.File{ BuildID: 1, @@ -100,10 +98,9 @@ func TestFileList(t *testing.T) { } func TestFileIndexes(t *testing.T) { - db := openTest() - defer db.Close() + s := newTest() + defer s.Close() - s := From(db) if err := s.FileCreate( &model.File{ BuildID: 1, @@ -134,10 +131,10 @@ func TestFileIndexes(t *testing.T) { } // func TestFileCascade(t *testing.T) { -// db := openTest() -// defer db.Close() +// s := newTest() +// defer s.Close() +// // -// s := From(db) // err1 := s.ProcCreate([]*model.Proc{ // { // BuildID: 1, diff --git a/store/datastore/procs.go b/store/datastore/procs.go index 49f3fda9..61d70461 100644 --- a/store/datastore/procs.go +++ b/store/datastore/procs.go @@ -7,21 +7,21 @@ import ( ) func (db *datastore) ProcFind(build *model.Build, pid int) (*model.Proc, error) { - stmt := sql.Lookup(sql.DriverSqlite, "procs-find-build-pid") + stmt := sql.Lookup(db.driver, "procs-find-build-pid") proc := new(model.Proc) err := meddler.QueryRow(db, proc, stmt, build.ID, pid) return proc, err } func (db *datastore) ProcChild(build *model.Build, pid int, child string) (*model.Proc, error) { - stmt := sql.Lookup(sql.DriverSqlite, "procs-find-build-ppid") + stmt := sql.Lookup(db.driver, "procs-find-build-ppid") proc := new(model.Proc) err := meddler.QueryRow(db, proc, stmt, build.ID, pid, child) return proc, err } func (db *datastore) ProcList(build *model.Build) ([]*model.Proc, error) { - stmt := sql.Lookup(sql.DriverSqlite, "procs-find-build") + stmt := sql.Lookup(db.driver, "procs-find-build") list := []*model.Proc{} err := meddler.QueryAll(db, &list, stmt, build.ID) return list, err diff --git a/store/datastore/procs_test.go b/store/datastore/procs_test.go index e0eb4c37..16c69ec9 100644 --- a/store/datastore/procs_test.go +++ b/store/datastore/procs_test.go @@ -7,10 +7,9 @@ import ( ) func TestProcFind(t *testing.T) { - db := openTest() - defer db.Close() + s := newTest() + defer s.Close() - s := From(db) err := s.ProcCreate([]*model.Proc{ { BuildID: 1000, @@ -57,10 +56,9 @@ func TestProcFind(t *testing.T) { } func TestProcChild(t *testing.T) { - db := openTest() - defer db.Close() + s := newTest() + defer s.Close() - s := From(db) err := s.ProcCreate([]*model.Proc{ { BuildID: 1, @@ -97,10 +95,9 @@ func TestProcChild(t *testing.T) { } func TestProcList(t *testing.T) { - db := openTest() - defer db.Close() + s := newTest() + defer s.Close() - s := From(db) err := s.ProcCreate([]*model.Proc{ { BuildID: 2, @@ -140,10 +137,9 @@ func TestProcList(t *testing.T) { } func TestProcUpdate(t *testing.T) { - db := openTest() - defer db.Close() + s := newTest() + defer s.Close() - s := From(db) proc := &model.Proc{ BuildID: 1, PID: 1, @@ -177,10 +173,9 @@ func TestProcUpdate(t *testing.T) { } func TestProcIndexes(t *testing.T) { - db := openTest() - defer db.Close() + s := newTest() + defer s.Close() - s := From(db) if err := s.ProcCreate([]*model.Proc{ { BuildID: 1, diff --git a/store/datastore/sql/lookup.go b/store/datastore/sql/lookup.go index 5f3bc217..6d9550af 100644 --- a/store/datastore/sql/lookup.go +++ b/store/datastore/sql/lookup.go @@ -1,12 +1,13 @@ package sql import ( + "github.com/drone/drone/store/datastore/sql/postgres" "github.com/drone/drone/store/datastore/sql/sqlite" ) // Supported database drivers const ( - DriverSqlite = "sqlite" + DriverSqlite = "sqlite3" DriverMysql = "mysql" DriverPostgres = "postgres" ) @@ -15,6 +16,8 @@ const ( // the specified database driver. func Lookup(driver string, name string) string { switch driver { + case DriverPostgres: + return postgres.Lookup(name) default: return sqlite.Lookup(name) } diff --git a/store/datastore/sql/postgres/files/files.sql b/store/datastore/sql/postgres/files/files.sql new file mode 100644 index 00000000..21eece90 --- /dev/null +++ b/store/datastore/sql/postgres/files/files.sql @@ -0,0 +1,41 @@ +-- name: files-find-build + +SELECT + file_id +,file_build_id +,file_proc_id +,file_name +,file_mime +,file_size +,file_time +FROM files +WHERE file_build_id = $1 + +-- name: files-find-proc-name + +SELECT + file_id +,file_build_id +,file_proc_id +,file_name +,file_mime +,file_size +,file_time +FROM files +WHERE file_proc_id = $1 + AND file_name = $2 + +-- name: files-find-proc-name-data + +SELECT + file_id +,file_build_id +,file_proc_id +,file_name +,file_mime +,file_size +,file_time +,file_data +FROM files +WHERE file_proc_id = $1 + AND file_name = $2 diff --git a/store/datastore/sql/postgres/files/procs.sql b/store/datastore/sql/postgres/files/procs.sql new file mode 100644 index 00000000..34bf7655 --- /dev/null +++ b/store/datastore/sql/postgres/files/procs.sql @@ -0,0 +1,62 @@ +-- name: procs-find-build + +SELECT + proc_id +,proc_build_id +,proc_pid +,proc_ppid +,proc_pgid +,proc_name +,proc_state +,proc_error +,proc_exit_code +,proc_started +,proc_stopped +,proc_machine +,proc_platform +,proc_environ +FROM procs +WHERE proc_build_id = $1 + +-- name: procs-find-build-pid + +SELECT +proc_id +,proc_build_id +,proc_pid +,proc_ppid +,proc_pgid +,proc_name +,proc_state +,proc_error +,proc_exit_code +,proc_started +,proc_stopped +,proc_machine +,proc_platform +,proc_environ +FROM procs +WHERE proc_build_id = $1 + AND proc_pid = $2 + +-- name: procs-find-build-ppid + +SELECT +proc_id +,proc_build_id +,proc_pid +,proc_ppid +,proc_pgid +,proc_name +,proc_state +,proc_error +,proc_exit_code +,proc_started +,proc_stopped +,proc_machine +,proc_platform +,proc_environ +FROM procs +WHERE proc_build_id = $1 + AND proc_ppid = $2 + AND proc_name = $3 diff --git a/store/datastore/sql/postgres/sql.go b/store/datastore/sql/postgres/sql.go new file mode 100644 index 00000000..2b0b6488 --- /dev/null +++ b/store/datastore/sql/postgres/sql.go @@ -0,0 +1,3 @@ +package postgres + +//go:generate sqlbin sql --package=postgres diff --git a/store/datastore/sql/postgres/sql_gen.go b/store/datastore/sql/postgres/sql_gen.go new file mode 100644 index 00000000..b2e1024c --- /dev/null +++ b/store/datastore/sql/postgres/sql_gen.go @@ -0,0 +1,120 @@ +package postgres + +// Lookup returns the named statement. +func Lookup(name string) string { + return index[name] +} + +var index = map[string]string{ + "files-find-build": filesFindBuild, + "files-find-proc-name": filesFindProcName, + "files-find-proc-name-data": filesFindProcNameData, + "procs-find-build": procsFindBuild, + "procs-find-build-pid": procsFindBuildPid, + "procs-find-build-ppid": procsFindBuildPpid, +} + +var filesFindBuild = ` +SELECT + file_id +,file_build_id +,file_proc_id +,file_name +,file_mime +,file_size +,file_time +FROM files +WHERE file_build_id = $1 +` + +var filesFindProcName = ` +SELECT + file_id +,file_build_id +,file_proc_id +,file_name +,file_mime +,file_size +,file_time +FROM files +WHERE file_proc_id = $1 + AND file_name = $2 +` + +var filesFindProcNameData = ` +SELECT + file_id +,file_build_id +,file_proc_id +,file_name +,file_mime +,file_size +,file_time +,file_data +FROM files +WHERE file_proc_id = $1 + AND file_name = $2 +` + +var procsFindBuild = ` +SELECT + proc_id +,proc_build_id +,proc_pid +,proc_ppid +,proc_pgid +,proc_name +,proc_state +,proc_error +,proc_exit_code +,proc_started +,proc_stopped +,proc_machine +,proc_platform +,proc_environ +FROM procs +WHERE proc_build_id = $1 +` + +var procsFindBuildPid = ` +SELECT +proc_id +,proc_build_id +,proc_pid +,proc_ppid +,proc_pgid +,proc_name +,proc_state +,proc_error +,proc_exit_code +,proc_started +,proc_stopped +,proc_machine +,proc_platform +,proc_environ +FROM procs +WHERE proc_build_id = $1 + AND proc_pid = $2 +` + +var procsFindBuildPpid = ` +SELECT +proc_id +,proc_build_id +,proc_pid +,proc_ppid +,proc_pgid +,proc_name +,proc_state +,proc_error +,proc_exit_code +,proc_started +,proc_stopped +,proc_machine +,proc_platform +,proc_environ +FROM procs +WHERE proc_build_id = $1 + AND proc_ppid = $2 + AND proc_name = $3 +` diff --git a/store/datastore/store.go b/store/datastore/store.go index 2d593613..28798176 100644 --- a/store/datastore/store.go +++ b/store/datastore/store.go @@ -17,19 +17,24 @@ import ( // of the sql/database driver with a relational database backend. type datastore struct { *sql.DB + + driver string + config string } // New creates a database connection for the given driver and datasource // and returns a new Store. func New(driver, config string) store.Store { - return From( - open(driver, config), - ) + return &datastore{ + DB: open(driver, config), + driver: driver, + config: config, + } } // From returns a Store using an existing database connection. func From(db *sql.DB) store.Store { - return &datastore{db} + return &datastore{DB: db} } // open opens a new database connection with the specified @@ -60,7 +65,7 @@ func open(driver, config string) *sql.DB { return db } -// OpenTest opens a new database connection for testing purposes. +// openTest opens a new database connection for testing purposes. // The database driver and connection string are provided by // environment variables, with fallback to in-memory sqlite. func openTest() *sql.DB { @@ -75,6 +80,25 @@ func openTest() *sql.DB { return open(driver, config) } +// newTest creates a new database connection for testing purposes. +// The database driver and connection string are provided by +// environment variables, with fallback to in-memory sqlite. +func newTest() *datastore { + var ( + driver = "sqlite3" + config = ":memory:" + ) + if os.Getenv("DATABASE_DRIVER") != "" { + driver = os.Getenv("DATABASE_DRIVER") + config = os.Getenv("DATABASE_CONFIG") + } + return &datastore{ + DB: open(driver, config), + driver: driver, + config: config, + } +} + // helper function to ping the database with backoff to ensure // a connection can be established before we proceed with the // database setup and migration.