// Code generated by sqlc. DO NOT EDIT.
// source: workflows.sql

package db

import (
	"context"
	"database/sql"
	"time"

	"github.com/google/uuid"
)

const createTask = `-- name: CreateTask :one
INSERT INTO tasks (workflow_id, name, finished, result, error, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING workflow_id, name, finished, result, error, created_at, updated_at
`

type CreateTaskParams struct {
	WorkflowID uuid.UUID
	Name       string
	Finished   bool
	Result     sql.NullString
	Error      sql.NullString
	CreatedAt  time.Time
	UpdatedAt  time.Time
}

func (q *Queries) CreateTask(ctx context.Context, arg CreateTaskParams) (Task, error) {
	row := q.db.QueryRow(ctx, createTask,
		arg.WorkflowID,
		arg.Name,
		arg.Finished,
		arg.Result,
		arg.Error,
		arg.CreatedAt,
		arg.UpdatedAt,
	)
	var i Task
	err := row.Scan(
		&i.WorkflowID,
		&i.Name,
		&i.Finished,
		&i.Result,
		&i.Error,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const createTaskLog = `-- name: CreateTaskLog :one
INSERT INTO task_logs (workflow_id, task_name, body)
VALUES ($1, $2, $3)
RETURNING id, workflow_id, task_name, body, created_at, updated_at
`

type CreateTaskLogParams struct {
	WorkflowID uuid.UUID
	TaskName   string
	Body       string
}

func (q *Queries) CreateTaskLog(ctx context.Context, arg CreateTaskLogParams) (TaskLog, error) {
	row := q.db.QueryRow(ctx, createTaskLog, arg.WorkflowID, arg.TaskName, arg.Body)
	var i TaskLog
	err := row.Scan(
		&i.ID,
		&i.WorkflowID,
		&i.TaskName,
		&i.Body,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const createWorkflow = `-- name: CreateWorkflow :one
INSERT INTO workflows (id, params, name, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, params, name, created_at, updated_at, finished, output, error
`

type CreateWorkflowParams struct {
	ID        uuid.UUID
	Params    sql.NullString
	Name      sql.NullString
	CreatedAt time.Time
	UpdatedAt time.Time
}

func (q *Queries) CreateWorkflow(ctx context.Context, arg CreateWorkflowParams) (Workflow, error) {
	row := q.db.QueryRow(ctx, createWorkflow,
		arg.ID,
		arg.Params,
		arg.Name,
		arg.CreatedAt,
		arg.UpdatedAt,
	)
	var i Workflow
	err := row.Scan(
		&i.ID,
		&i.Params,
		&i.Name,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Finished,
		&i.Output,
		&i.Error,
	)
	return i, err
}

const taskLogs = `-- name: TaskLogs :many
SELECT task_logs.id, task_logs.workflow_id, task_logs.task_name, task_logs.body, task_logs.created_at, task_logs.updated_at
FROM task_logs
ORDER BY created_at
`

func (q *Queries) TaskLogs(ctx context.Context) ([]TaskLog, error) {
	rows, err := q.db.Query(ctx, taskLogs)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []TaskLog
	for rows.Next() {
		var i TaskLog
		if err := rows.Scan(
			&i.ID,
			&i.WorkflowID,
			&i.TaskName,
			&i.Body,
			&i.CreatedAt,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const taskLogsForTask = `-- name: TaskLogsForTask :many
SELECT task_logs.id, task_logs.workflow_id, task_logs.task_name, task_logs.body, task_logs.created_at, task_logs.updated_at
FROM task_logs
WHERE workflow_id = $1
  AND task_name = $2
ORDER BY created_at
`

type TaskLogsForTaskParams struct {
	WorkflowID uuid.UUID
	TaskName   string
}

func (q *Queries) TaskLogsForTask(ctx context.Context, arg TaskLogsForTaskParams) ([]TaskLog, error) {
	rows, err := q.db.Query(ctx, taskLogsForTask, arg.WorkflowID, arg.TaskName)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []TaskLog
	for rows.Next() {
		var i TaskLog
		if err := rows.Scan(
			&i.ID,
			&i.WorkflowID,
			&i.TaskName,
			&i.Body,
			&i.CreatedAt,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const tasks = `-- name: Tasks :many
SELECT tasks.workflow_id, tasks.name, tasks.finished, tasks.result, tasks.error, tasks.created_at, tasks.updated_at
FROM tasks
ORDER BY created_at
`

func (q *Queries) Tasks(ctx context.Context) ([]Task, error) {
	rows, err := q.db.Query(ctx, tasks)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Task
	for rows.Next() {
		var i Task
		if err := rows.Scan(
			&i.WorkflowID,
			&i.Name,
			&i.Finished,
			&i.Result,
			&i.Error,
			&i.CreatedAt,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const tasksForWorkflow = `-- name: TasksForWorkflow :many
SELECT tasks.workflow_id, tasks.name, tasks.finished, tasks.result, tasks.error, tasks.created_at, tasks.updated_at
FROM tasks
WHERE workflow_id = $1
ORDER BY created_at
`

func (q *Queries) TasksForWorkflow(ctx context.Context, workflowID uuid.UUID) ([]Task, error) {
	rows, err := q.db.Query(ctx, tasksForWorkflow, workflowID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Task
	for rows.Next() {
		var i Task
		if err := rows.Scan(
			&i.WorkflowID,
			&i.Name,
			&i.Finished,
			&i.Result,
			&i.Error,
			&i.CreatedAt,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const unfinishedWorkflows = `-- name: UnfinishedWorkflows :many
SELECT workflows.id, workflows.params, workflows.name, workflows.created_at, workflows.updated_at, workflows.finished, workflows.output, workflows.error
FROM workflows
WHERE workflows.finished = false
`

func (q *Queries) UnfinishedWorkflows(ctx context.Context) ([]Workflow, error) {
	rows, err := q.db.Query(ctx, unfinishedWorkflows)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Workflow
	for rows.Next() {
		var i Workflow
		if err := rows.Scan(
			&i.ID,
			&i.Params,
			&i.Name,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.Finished,
			&i.Output,
			&i.Error,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const upsertTask = `-- name: UpsertTask :one
INSERT INTO tasks (workflow_id, name, finished, result, error, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (workflow_id, name) DO UPDATE
    SET workflow_id = excluded.workflow_id,
        name        = excluded.name,
        finished    = excluded.finished,
        result      = excluded.result,
        updated_at  = excluded.updated_at
RETURNING workflow_id, name, finished, result, error, created_at, updated_at
`

type UpsertTaskParams struct {
	WorkflowID uuid.UUID
	Name       string
	Finished   bool
	Result     sql.NullString
	Error      sql.NullString
	CreatedAt  time.Time
	UpdatedAt  time.Time
}

func (q *Queries) UpsertTask(ctx context.Context, arg UpsertTaskParams) (Task, error) {
	row := q.db.QueryRow(ctx, upsertTask,
		arg.WorkflowID,
		arg.Name,
		arg.Finished,
		arg.Result,
		arg.Error,
		arg.CreatedAt,
		arg.UpdatedAt,
	)
	var i Task
	err := row.Scan(
		&i.WorkflowID,
		&i.Name,
		&i.Finished,
		&i.Result,
		&i.Error,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const workflow = `-- name: Workflow :one
SELECT id, params, name, created_at, updated_at, finished, output, error
FROM workflows
WHERE id = $1
`

func (q *Queries) Workflow(ctx context.Context, id uuid.UUID) (Workflow, error) {
	row := q.db.QueryRow(ctx, workflow, id)
	var i Workflow
	err := row.Scan(
		&i.ID,
		&i.Params,
		&i.Name,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Finished,
		&i.Output,
		&i.Error,
	)
	return i, err
}

const workflowFinished = `-- name: WorkflowFinished :one
UPDATE workflows
SET finished   = $2,
    output     = $3,
    updated_at = $4
WHERE workflows.id = $1
RETURNING id, params, name, created_at, updated_at, finished, output, error
`

type WorkflowFinishedParams struct {
	ID        uuid.UUID
	Finished  bool
	Output    string
	UpdatedAt time.Time
}

func (q *Queries) WorkflowFinished(ctx context.Context, arg WorkflowFinishedParams) (Workflow, error) {
	row := q.db.QueryRow(ctx, workflowFinished,
		arg.ID,
		arg.Finished,
		arg.Output,
		arg.UpdatedAt,
	)
	var i Workflow
	err := row.Scan(
		&i.ID,
		&i.Params,
		&i.Name,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Finished,
		&i.Output,
		&i.Error,
	)
	return i, err
}

const workflows = `-- name: Workflows :many

SELECT id, params, name, created_at, updated_at, finished, output, error
FROM workflows
ORDER BY created_at DESC
`

// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
func (q *Queries) Workflows(ctx context.Context) ([]Workflow, error) {
	rows, err := q.db.Query(ctx, workflows)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Workflow
	for rows.Next() {
		var i Workflow
		if err := rows.Scan(
			&i.ID,
			&i.Params,
			&i.Name,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.Finished,
			&i.Output,
			&i.Error,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}
