package clusterdb

import "database/sql"

//DriverQueryFactory is a factory that chooses the precise DriverQueries implementation to use based on queries against the given database
type DriverQueryFactory interface {
	BuildDriverQueries(conn *sql.DB) (DriverQueries, error)
}

//DriverQueries is an interface that abstracts away the DB flavor specific details of querying databases for cluster management
type DriverQueries interface {
	//CanLockUsers returns whether this backing database supports user lock/unlock to prevent logins for a particular user
	CanLockUsers() bool

	//CanUseRolePairs returns whether this backing database supports HA password rotations with role pairs
	CanUseRolePairs() bool

	// TestConnection tests the DB connection by sending a SELECT 1, because sometimes the connection process
	// itself doesn't error.
	TestConnection(db *sql.DB) error

	// AlterPassword modifies the DB user's password in the clusterDB
	AlterPassword(db *sql.DB, username string, password string) (sql.Result, error)

	// SetUserLock sets the DB user to locked or unlocked for logins
	SetUserLock(db *sql.DB, username string, locked bool) (sql.Result, error)

	// CreateRole makes a new blank DB role in the cluster db
	CreateRole(db *sql.DB, rolename string) (sql.Result, error)

	// CreateUser makes a new DB user in the cluster db, with password and an inherited role
	CreateUser(db *sql.DB, username string, password string, parentRole string) (sql.Result, error)

	// RoleParents returns a list of role inheritance relationships in the clusterDb, as a map
	// of role name -> list of member role names
	RoleParents(db *sql.DB) (*sql.Rows, error)

	// GrantedRoles returns a list of role names who have grants in the cluster DB
	GrantedRoles(db *sql.DB) (*sql.Rows, error)

	// ActiveUsers returns a list of users currently executing a query on the server
	ActiveUsers(db *sql.DB) (*sql.Rows, error)

	// ClusterUsers retrieves all users in the cluster DB, as a map of username -> locked/unlocked  If true, unlocked, if false locked
	ClusterUsers(db *sql.DB) (*sql.Rows, error)
}
