mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: workspace filter query supported in backend (#2232)
* feat: add support for template in workspace filter * feat: Implement workspace search filter to support names * Use new query param parser for pagination fields * Remove excessive calls, use filters on a single query Co-authored-by: Garrett <garrett@coder.com>
This commit is contained in:
@@ -321,41 +321,47 @@ func (q *fakeQuerier) GetWorkspacesWithFilter(_ context.Context, arg database.Ge
|
||||
|
||||
workspaces := make([]database.Workspace, 0)
|
||||
for _, workspace := range q.workspaces {
|
||||
if arg.OrganizationID != uuid.Nil && workspace.OrganizationID != arg.OrganizationID {
|
||||
continue
|
||||
}
|
||||
if arg.OwnerID != uuid.Nil && workspace.OwnerID != arg.OwnerID {
|
||||
continue
|
||||
}
|
||||
if arg.OwnerUsername != "" {
|
||||
owner, err := q.GetUserByID(context.Background(), workspace.OwnerID)
|
||||
if err == nil && arg.OwnerUsername != owner.Username {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if arg.TemplateName != "" {
|
||||
templates, err := q.GetTemplatesWithFilter(context.Background(), database.GetTemplatesWithFilterParams{
|
||||
ExactName: arg.TemplateName,
|
||||
})
|
||||
// Add to later param
|
||||
if err == nil {
|
||||
for _, t := range templates {
|
||||
arg.TemplateIds = append(arg.TemplateIds, t.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !arg.Deleted && workspace.Deleted {
|
||||
continue
|
||||
}
|
||||
if arg.Name != "" && !strings.Contains(workspace.Name, arg.Name) {
|
||||
continue
|
||||
}
|
||||
workspaces = append(workspaces, workspace)
|
||||
}
|
||||
|
||||
return workspaces, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspacesByTemplateID(_ context.Context, arg database.GetWorkspacesByTemplateIDParams) ([]database.Workspace, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
workspaces := make([]database.Workspace, 0)
|
||||
for _, workspace := range q.workspaces {
|
||||
if workspace.TemplateID.String() != arg.TemplateID.String() {
|
||||
continue
|
||||
}
|
||||
if workspace.Deleted != arg.Deleted {
|
||||
continue
|
||||
if len(arg.TemplateIds) > 0 {
|
||||
match := false
|
||||
for _, id := range arg.TemplateIds {
|
||||
if workspace.TemplateID == id {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
}
|
||||
workspaces = append(workspaces, workspace)
|
||||
}
|
||||
if len(workspaces) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
|
||||
return workspaces, nil
|
||||
}
|
||||
|
||||
@@ -641,25 +647,6 @@ func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(_ context.Con
|
||||
return database.WorkspaceBuild{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspacesByOrganizationIDs(_ context.Context, req database.GetWorkspacesByOrganizationIDsParams) ([]database.Workspace, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
workspaces := make([]database.Workspace, 0)
|
||||
for _, workspace := range q.workspaces {
|
||||
for _, id := range req.Ids {
|
||||
if workspace.OrganizationID != id {
|
||||
continue
|
||||
}
|
||||
if workspace.Deleted != req.Deleted {
|
||||
continue
|
||||
}
|
||||
workspaces = append(workspaces, workspace)
|
||||
}
|
||||
}
|
||||
return workspaces, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetOrganizations(_ context.Context) ([]database.Organization, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -786,6 +773,44 @@ func (q *fakeQuerier) UpdateTemplateMetaByID(_ context.Context, arg database.Upd
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetTemplatesWithFilter(_ context.Context, arg database.GetTemplatesWithFilterParams) ([]database.Template, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
var templates []database.Template
|
||||
for _, template := range q.templates {
|
||||
if template.Deleted != arg.Deleted {
|
||||
continue
|
||||
}
|
||||
if arg.OrganizationID != uuid.Nil && template.OrganizationID != arg.OrganizationID {
|
||||
continue
|
||||
}
|
||||
|
||||
if arg.ExactName != "" && !strings.EqualFold(template.Name, arg.ExactName) {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(arg.Ids) > 0 {
|
||||
match := false
|
||||
for _, id := range arg.Ids {
|
||||
if template.ID == id {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
}
|
||||
templates = append(templates, template)
|
||||
}
|
||||
if len(templates) > 0 {
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetTemplateVersionsByTemplateID(_ context.Context, arg database.GetTemplateVersionsByTemplateIDParams) (version []database.TemplateVersion, err error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -923,45 +948,6 @@ func (q *fakeQuerier) GetParameterValueByScopeAndName(_ context.Context, arg dat
|
||||
return database.ParameterValue{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetTemplatesByOrganization(_ context.Context, arg database.GetTemplatesByOrganizationParams) ([]database.Template, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
templates := make([]database.Template, 0)
|
||||
for _, template := range q.templates {
|
||||
if template.Deleted != arg.Deleted {
|
||||
continue
|
||||
}
|
||||
if template.OrganizationID != arg.OrganizationID {
|
||||
continue
|
||||
}
|
||||
templates = append(templates, template)
|
||||
}
|
||||
if len(templates) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetTemplatesByIDs(_ context.Context, ids []uuid.UUID) ([]database.Template, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
templates := make([]database.Template, 0)
|
||||
for _, template := range q.templates {
|
||||
for _, id := range ids {
|
||||
if template.ID.String() != id.String() {
|
||||
continue
|
||||
}
|
||||
templates = append(templates, template)
|
||||
}
|
||||
}
|
||||
if len(templates) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetOrganizationMemberByUserID(_ context.Context, arg database.GetOrganizationMemberByUserIDParams) (database.OrganizationMember, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package databasefake_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
|
||||
"github.com/coder/coder/coderd/database/databasefake"
|
||||
)
|
||||
|
||||
// TestExactMethods will ensure the fake database does not hold onto excessive
|
||||
// functions. The fake database is a manual implementation, so it is possible
|
||||
// we forget to delete functions that we remove. This unit test just ensures
|
||||
// we remove the extra methods.
|
||||
func TestExactMethods(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// extraFakeMethods contains the extra allowed methods that are not a part
|
||||
// of the database.Store interface.
|
||||
extraFakeMethods := map[string]string{
|
||||
// Example
|
||||
// "SortFakeLists": "Helper function used",
|
||||
}
|
||||
|
||||
fake := reflect.TypeOf(databasefake.New())
|
||||
fakeMethods := methods(fake)
|
||||
|
||||
store := reflect.TypeOf((*database.Store)(nil)).Elem()
|
||||
storeMethods := methods(store)
|
||||
|
||||
// Store should be a subset
|
||||
for k := range storeMethods {
|
||||
_, ok := fakeMethods[k]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("This should never happen. FakeDB missing method %s, so doesn't fit the interface", k))
|
||||
}
|
||||
delete(storeMethods, k)
|
||||
delete(fakeMethods, k)
|
||||
}
|
||||
|
||||
for k := range fakeMethods {
|
||||
_, ok := extraFakeMethods[k]
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
// If you are seeing this error, you have an extra function not required
|
||||
// for the database.Store. If you still want to keep it, add it to
|
||||
// 'extraFakeMethods' to allow it.
|
||||
t.Errorf("Fake method '%s()' is excessive and not needed to fit interface, delete it", k)
|
||||
}
|
||||
}
|
||||
|
||||
func methods(rt reflect.Type) map[string]bool {
|
||||
methods := make(map[string]bool)
|
||||
for i := 0; i < rt.NumMethod(); i++ {
|
||||
methods[rt.Method(i).Name] = true
|
||||
}
|
||||
return methods
|
||||
}
|
||||
@@ -53,8 +53,7 @@ type querier interface {
|
||||
GetTemplateVersionByJobID(ctx context.Context, jobID uuid.UUID) (TemplateVersion, error)
|
||||
GetTemplateVersionByTemplateIDAndName(ctx context.Context, arg GetTemplateVersionByTemplateIDAndNameParams) (TemplateVersion, error)
|
||||
GetTemplateVersionsByTemplateID(ctx context.Context, arg GetTemplateVersionsByTemplateIDParams) ([]TemplateVersion, error)
|
||||
GetTemplatesByIDs(ctx context.Context, ids []uuid.UUID) ([]Template, error)
|
||||
GetTemplatesByOrganization(ctx context.Context, arg GetTemplatesByOrganizationParams) ([]Template, error)
|
||||
GetTemplatesWithFilter(ctx context.Context, arg GetTemplatesWithFilterParams) ([]Template, error)
|
||||
GetUserByEmailOrUsername(ctx context.Context, arg GetUserByEmailOrUsernameParams) (User, error)
|
||||
GetUserByID(ctx context.Context, id uuid.UUID) (User, error)
|
||||
GetUserCount(ctx context.Context) (int64, error)
|
||||
@@ -78,8 +77,6 @@ type querier interface {
|
||||
GetWorkspaceResourceByID(ctx context.Context, id uuid.UUID) (WorkspaceResource, error)
|
||||
GetWorkspaceResourcesByJobID(ctx context.Context, jobID uuid.UUID) ([]WorkspaceResource, error)
|
||||
GetWorkspacesAutostart(ctx context.Context) ([]Workspace, error)
|
||||
GetWorkspacesByOrganizationIDs(ctx context.Context, arg GetWorkspacesByOrganizationIDsParams) ([]Workspace, error)
|
||||
GetWorkspacesByTemplateID(ctx context.Context, arg GetWorkspacesByTemplateIDParams) ([]Workspace, error)
|
||||
GetWorkspacesWithFilter(ctx context.Context, arg GetWorkspacesWithFilterParams) ([]Workspace, error)
|
||||
InsertAPIKey(ctx context.Context, arg InsertAPIKeyParams) (APIKey, error)
|
||||
InsertAuditLog(ctx context.Context, arg InsertAuditLogParams) (AuditLog, error)
|
||||
|
||||
+69
-163
@@ -1671,68 +1671,48 @@ func (q *sqlQuerier) GetTemplateByOrganizationAndName(ctx context.Context, arg G
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTemplatesByIDs = `-- name: GetTemplatesByIDs :many
|
||||
const getTemplatesWithFilter = `-- name: GetTemplatesWithFilter :many
|
||||
SELECT
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, max_ttl, min_autostart_interval, created_by
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
id = ANY($1 :: uuid [ ])
|
||||
-- Optionally include deleted templates
|
||||
templates.deleted = $1
|
||||
-- Filter by organization_id
|
||||
AND CASE
|
||||
WHEN $2 :: uuid != '00000000-00000000-00000000-00000000' THEN
|
||||
organization_id = $2
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by exact name
|
||||
AND CASE
|
||||
WHEN $3 :: text != '' THEN
|
||||
LOWER("name") = LOWER($3)
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by ids
|
||||
AND CASE
|
||||
WHEN array_length($4 :: uuid[], 1) > 0 THEN
|
||||
id = ANY($4)
|
||||
ELSE true
|
||||
END
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetTemplatesByIDs(ctx context.Context, ids []uuid.UUID) ([]Template, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTemplatesByIDs, pq.Array(ids))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Template
|
||||
for rows.Next() {
|
||||
var i Template
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.OrganizationID,
|
||||
&i.Deleted,
|
||||
&i.Name,
|
||||
&i.Provisioner,
|
||||
&i.ActiveVersionID,
|
||||
&i.Description,
|
||||
&i.MaxTtl,
|
||||
&i.MinAutostartInterval,
|
||||
&i.CreatedBy,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
type GetTemplatesWithFilterParams struct {
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
ExactName string `db:"exact_name" json:"exact_name"`
|
||||
Ids []uuid.UUID `db:"ids" json:"ids"`
|
||||
}
|
||||
|
||||
const getTemplatesByOrganization = `-- name: GetTemplatesByOrganization :many
|
||||
SELECT
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, max_ttl, min_autostart_interval, created_by
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
organization_id = $1
|
||||
AND deleted = $2
|
||||
`
|
||||
|
||||
type GetTemplatesByOrganizationParams struct {
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetTemplatesByOrganization(ctx context.Context, arg GetTemplatesByOrganizationParams) ([]Template, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTemplatesByOrganization, arg.OrganizationID, arg.Deleted)
|
||||
func (q *sqlQuerier) GetTemplatesWithFilter(ctx context.Context, arg GetTemplatesWithFilterParams) ([]Template, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTemplatesWithFilter,
|
||||
arg.Deleted,
|
||||
arg.OrganizationID,
|
||||
arg.ExactName,
|
||||
pq.Array(arg.Ids),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -3639,98 +3619,6 @@ func (q *sqlQuerier) GetWorkspacesAutostart(ctx context.Context) ([]Workspace, e
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getWorkspacesByOrganizationIDs = `-- name: GetWorkspacesByOrganizationIDs :many
|
||||
SELECT id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl FROM workspaces WHERE organization_id = ANY($1 :: uuid [ ]) AND deleted = $2
|
||||
`
|
||||
|
||||
type GetWorkspacesByOrganizationIDsParams struct {
|
||||
Ids []uuid.UUID `db:"ids" json:"ids"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetWorkspacesByOrganizationIDs(ctx context.Context, arg GetWorkspacesByOrganizationIDsParams) ([]Workspace, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getWorkspacesByOrganizationIDs, pq.Array(arg.Ids), arg.Deleted)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Workspace
|
||||
for rows.Next() {
|
||||
var i Workspace
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.OwnerID,
|
||||
&i.OrganizationID,
|
||||
&i.TemplateID,
|
||||
&i.Deleted,
|
||||
&i.Name,
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getWorkspacesByTemplateID = `-- name: GetWorkspacesByTemplateID :many
|
||||
SELECT
|
||||
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl
|
||||
FROM
|
||||
workspaces
|
||||
WHERE
|
||||
template_id = $1
|
||||
AND deleted = $2
|
||||
`
|
||||
|
||||
type GetWorkspacesByTemplateIDParams struct {
|
||||
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetWorkspacesByTemplateID(ctx context.Context, arg GetWorkspacesByTemplateIDParams) ([]Workspace, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getWorkspacesByTemplateID, arg.TemplateID, arg.Deleted)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Workspace
|
||||
for rows.Next() {
|
||||
var i Workspace
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.OwnerID,
|
||||
&i.OrganizationID,
|
||||
&i.TemplateID,
|
||||
&i.Deleted,
|
||||
&i.Name,
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getWorkspacesWithFilter = `-- name: GetWorkspacesWithFilter :many
|
||||
SELECT
|
||||
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl
|
||||
@@ -3738,39 +3626,57 @@ FROM
|
||||
workspaces
|
||||
WHERE
|
||||
-- Optionally include deleted workspaces
|
||||
deleted = $1
|
||||
-- Filter by organization_id
|
||||
AND CASE
|
||||
WHEN $2 :: uuid != '00000000-00000000-00000000-00000000' THEN
|
||||
organization_id = $2
|
||||
ELSE true
|
||||
END
|
||||
workspaces.deleted = $1
|
||||
-- Filter by owner_id
|
||||
AND CASE
|
||||
WHEN $3 :: uuid != '00000000-00000000-00000000-00000000' THEN
|
||||
owner_id = $3
|
||||
ELSE true
|
||||
WHEN $2 :: uuid != '00000000-00000000-00000000-00000000' THEN
|
||||
owner_id = $2
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by owner_name
|
||||
AND CASE
|
||||
WHEN $3 :: text != '' THEN
|
||||
owner_id = (SELECT id FROM users WHERE username = $3)
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by template_name
|
||||
-- There can be more than 1 template with the same name across organizations.
|
||||
-- Use the organization filter to restrict to 1 org if needed.
|
||||
AND CASE
|
||||
WHEN $4 :: text != '' THEN
|
||||
template_id = ANY(SELECT id FROM templates WHERE name = $4)
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by template_ids
|
||||
AND CASE
|
||||
WHEN array_length($5 :: uuid[], 1) > 0 THEN
|
||||
template_id = ANY($5)
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by name, matching on substring
|
||||
AND CASE
|
||||
WHEN $4 :: text != '' THEN
|
||||
LOWER(name) LIKE '%' || LOWER($4) || '%'
|
||||
ELSE true
|
||||
WHEN $6 :: text != '' THEN
|
||||
LOWER(name) LIKE '%' || LOWER($6) || '%'
|
||||
ELSE true
|
||||
END
|
||||
`
|
||||
|
||||
type GetWorkspacesWithFilterParams struct {
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
|
||||
OwnerUsername string `db:"owner_username" json:"owner_username"`
|
||||
TemplateName string `db:"template_name" json:"template_name"`
|
||||
TemplateIds []uuid.UUID `db:"template_ids" json:"template_ids"`
|
||||
Name string `db:"name" json:"name"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetWorkspacesWithFilter(ctx context.Context, arg GetWorkspacesWithFilterParams) ([]Workspace, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getWorkspacesWithFilter,
|
||||
arg.Deleted,
|
||||
arg.OrganizationID,
|
||||
arg.OwnerID,
|
||||
arg.OwnerUsername,
|
||||
arg.TemplateName,
|
||||
pq.Array(arg.TemplateIds),
|
||||
arg.Name,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -8,13 +8,33 @@ WHERE
|
||||
LIMIT
|
||||
1;
|
||||
|
||||
-- name: GetTemplatesByIDs :many
|
||||
-- name: GetTemplatesWithFilter :many
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
id = ANY(@ids :: uuid [ ]);
|
||||
-- Optionally include deleted templates
|
||||
templates.deleted = @deleted
|
||||
-- Filter by organization_id
|
||||
AND CASE
|
||||
WHEN @organization_id :: uuid != '00000000-00000000-00000000-00000000' THEN
|
||||
organization_id = @organization_id
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by exact name
|
||||
AND CASE
|
||||
WHEN @exact_name :: text != '' THEN
|
||||
LOWER("name") = LOWER(@exact_name)
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by ids
|
||||
AND CASE
|
||||
WHEN array_length(@ids :: uuid[], 1) > 0 THEN
|
||||
id = ANY(@ids)
|
||||
ELSE true
|
||||
END
|
||||
;
|
||||
|
||||
-- name: GetTemplateByOrganizationAndName :one
|
||||
SELECT
|
||||
@@ -28,15 +48,6 @@ WHERE
|
||||
LIMIT
|
||||
1;
|
||||
|
||||
-- name: GetTemplatesByOrganization :many
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
organization_id = $1
|
||||
AND deleted = $2;
|
||||
|
||||
-- name: InsertTemplate :one
|
||||
INSERT INTO
|
||||
templates (
|
||||
|
||||
@@ -15,30 +15,41 @@ FROM
|
||||
workspaces
|
||||
WHERE
|
||||
-- Optionally include deleted workspaces
|
||||
deleted = @deleted
|
||||
-- Filter by organization_id
|
||||
AND CASE
|
||||
WHEN @organization_id :: uuid != '00000000-00000000-00000000-00000000' THEN
|
||||
organization_id = @organization_id
|
||||
ELSE true
|
||||
END
|
||||
workspaces.deleted = @deleted
|
||||
-- Filter by owner_id
|
||||
AND CASE
|
||||
WHEN @owner_id :: uuid != '00000000-00000000-00000000-00000000' THEN
|
||||
owner_id = @owner_id
|
||||
ELSE true
|
||||
WHEN @owner_id :: uuid != '00000000-00000000-00000000-00000000' THEN
|
||||
owner_id = @owner_id
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by owner_name
|
||||
AND CASE
|
||||
WHEN @owner_username :: text != '' THEN
|
||||
owner_id = (SELECT id FROM users WHERE username = @owner_username)
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by template_name
|
||||
-- There can be more than 1 template with the same name across organizations.
|
||||
-- Use the organization filter to restrict to 1 org if needed.
|
||||
AND CASE
|
||||
WHEN @template_name :: text != '' THEN
|
||||
template_id = ANY(SELECT id FROM templates WHERE name = @template_name)
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by template_ids
|
||||
AND CASE
|
||||
WHEN array_length(@template_ids :: uuid[], 1) > 0 THEN
|
||||
template_id = ANY(@template_ids)
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by name, matching on substring
|
||||
AND CASE
|
||||
WHEN @name :: text != '' THEN
|
||||
LOWER(name) LIKE '%' || LOWER(@name) || '%'
|
||||
ELSE true
|
||||
WHEN @name :: text != '' THEN
|
||||
LOWER(name) LIKE '%' || LOWER(@name) || '%'
|
||||
ELSE true
|
||||
END
|
||||
;
|
||||
|
||||
-- name: GetWorkspacesByOrganizationIDs :many
|
||||
SELECT * FROM workspaces WHERE organization_id = ANY(@ids :: uuid [ ]) AND deleted = @deleted;
|
||||
|
||||
-- name: GetWorkspacesAutostart :many
|
||||
SELECT
|
||||
*
|
||||
@@ -53,15 +64,6 @@ AND
|
||||
(ttl IS NOT NULL AND ttl > 0)
|
||||
);
|
||||
|
||||
-- name: GetWorkspacesByTemplateID :many
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
workspaces
|
||||
WHERE
|
||||
template_id = $1
|
||||
AND deleted = $2;
|
||||
|
||||
-- name: GetWorkspaceByOwnerIDAndName :one
|
||||
SELECT
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user