mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
This commit introduces the `sqlcmig6` package, which at the time of this commit contains the same queries and models as `sqlc` package. Importantly though, once the kvdb to sql migration is made available in production, the `sqlcmig6` package will not change, as it is intended to represent the sql db as it was at the time of the migration. The sqlcmig6 package is therefore intended to be used in the kvdb to sql migration code, as it is will always be compatible with the sql database when all sql migrations prior to the kvdb to sql migration are applied. When additional sql migrations are added in the future, they may effect the `sqlc` package in such a way that the standard `sqlc` queries and models aren't compatible with kvdb to sql migration code any longer. By preserving the `sqlcmig6` package, we ensure that the kvdb to sql migration code can always use the same queries and models that were available at the time of the migration, even if the `sqlc` package changes in the future. Note that the `sqlcmig6` package have not been generated by `sqlc` (the queries and models are copied from the `sqlc` package), as it is not intended to be changed in the future.
210 lines
5.5 KiB
Go
210 lines
5.5 KiB
Go
package sqlcmig6
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// ActionQueryParams defines the parameters for querying actions.
|
|
type ActionQueryParams struct {
|
|
SessionID sql.NullInt64
|
|
AccountID sql.NullInt64
|
|
FeatureName sql.NullString
|
|
ActorName sql.NullString
|
|
RpcMethod sql.NullString
|
|
State sql.NullInt16
|
|
EndTime sql.NullTime
|
|
StartTime sql.NullTime
|
|
GroupID sql.NullInt64
|
|
}
|
|
|
|
// ListActionsParams defines the parameters for listing actions, including
|
|
// the ActionQueryParams for filtering and a Pagination struct for
|
|
// pagination. The Reversed field indicates whether the results should be
|
|
// returned in reverse order based on the created_at timestamp.
|
|
type ListActionsParams struct {
|
|
ActionQueryParams
|
|
Reversed bool
|
|
*Pagination
|
|
}
|
|
|
|
// Pagination defines the pagination parameters for listing actions.
|
|
type Pagination struct {
|
|
NumOffset int32
|
|
NumLimit int32
|
|
}
|
|
|
|
// ListActions retrieves a list of actions based on the provided
|
|
// ListActionsParams.
|
|
func (q *Queries) ListActions(ctx context.Context,
|
|
arg ListActionsParams) ([]Action, error) {
|
|
|
|
query, args := buildListActionsQuery(arg)
|
|
rows, err := q.db.QueryContext(ctx, fillPlaceHolders(query), args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Action
|
|
for rows.Next() {
|
|
var i Action
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.SessionID,
|
|
&i.AccountID,
|
|
&i.MacaroonIdentifier,
|
|
&i.ActorName,
|
|
&i.FeatureName,
|
|
&i.ActionTrigger,
|
|
&i.Intent,
|
|
&i.StructuredJsonData,
|
|
&i.RpcMethod,
|
|
&i.RpcParamsJson,
|
|
&i.CreatedAt,
|
|
&i.ActionState,
|
|
&i.ErrorReason,
|
|
); 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
|
|
}
|
|
|
|
// CountActions returns the number of actions that match the provided
|
|
// ActionQueryParams.
|
|
func (q *Queries) CountActions(ctx context.Context,
|
|
arg ActionQueryParams) (int64, error) {
|
|
|
|
query, args := buildActionsQuery(arg, true)
|
|
row := q.db.QueryRowContext(ctx, query, args...)
|
|
|
|
var count int64
|
|
err := row.Scan(&count)
|
|
|
|
return count, err
|
|
}
|
|
|
|
// buildActionsQuery constructs a SQL query to retrieve actions based on the
|
|
// provided parameters. We do this manually so that if, for example, we have
|
|
// a sessionID we are filtering by, then this appears in the query as:
|
|
// `WHERE a.session_id = ?` which will properly make use of the underlying
|
|
// index. If we were instead to use a single SQLC query, it would include many
|
|
// WHERE clauses like:
|
|
// "WHERE a.session_id = COALESCE(sqlc.narg('session_id'), a.session_id)".
|
|
// This would use the index if run against postres but not when run against
|
|
// sqlite.
|
|
//
|
|
// The 'count' param indicates whether the query should return a count of
|
|
// actions that match the criteria or the actions themselves.
|
|
func buildActionsQuery(params ActionQueryParams, count bool) (string, []any) {
|
|
var (
|
|
conditions []string
|
|
args []any
|
|
)
|
|
|
|
if params.SessionID.Valid {
|
|
conditions = append(conditions, "a.session_id = ?")
|
|
args = append(args, params.SessionID.Int64)
|
|
}
|
|
if params.AccountID.Valid {
|
|
conditions = append(conditions, "a.account_id = ?")
|
|
args = append(args, params.AccountID.Int64)
|
|
}
|
|
if params.FeatureName.Valid {
|
|
conditions = append(conditions, "a.feature_name = ?")
|
|
args = append(args, params.FeatureName.String)
|
|
}
|
|
if params.ActorName.Valid {
|
|
conditions = append(conditions, "a.actor_name = ?")
|
|
args = append(args, params.ActorName.String)
|
|
}
|
|
if params.RpcMethod.Valid {
|
|
conditions = append(conditions, "a.rpc_method = ?")
|
|
args = append(args, params.RpcMethod.String)
|
|
}
|
|
if params.State.Valid {
|
|
conditions = append(conditions, "a.action_state = ?")
|
|
args = append(args, params.State.Int16)
|
|
}
|
|
if params.EndTime.Valid {
|
|
conditions = append(conditions, "a.created_at <= ?")
|
|
args = append(args, params.EndTime.Time)
|
|
}
|
|
if params.StartTime.Valid {
|
|
conditions = append(conditions, "a.created_at >= ?")
|
|
args = append(args, params.StartTime.Time)
|
|
}
|
|
if params.GroupID.Valid {
|
|
conditions = append(conditions, `
|
|
EXISTS (
|
|
SELECT 1
|
|
FROM sessions s
|
|
WHERE s.id = a.session_id AND s.group_id = ?
|
|
)`)
|
|
args = append(args, params.GroupID.Int64)
|
|
}
|
|
|
|
query := "SELECT a.* FROM actions a"
|
|
if count {
|
|
query = "SELECT COUNT(*) FROM actions a"
|
|
}
|
|
if len(conditions) > 0 {
|
|
query += " WHERE " + strings.Join(conditions, " AND ")
|
|
}
|
|
|
|
return query, args
|
|
}
|
|
|
|
// buildListActionsQuery constructs a SQL query to retrieve a list of actions
|
|
// based on the provided parameters. It builds upon the `buildActionsQuery`
|
|
// function, adding pagination and ordering based on the reversed parameter.
|
|
func buildListActionsQuery(params ListActionsParams) (string, []interface{}) {
|
|
query, args := buildActionsQuery(params.ActionQueryParams, false)
|
|
|
|
// Determine order direction.
|
|
order := "ASC"
|
|
if params.Reversed {
|
|
order = "DESC"
|
|
}
|
|
query += " ORDER BY a.created_at " + order
|
|
|
|
// Maybe paginate.
|
|
if params.Pagination != nil {
|
|
query += " LIMIT ? OFFSET ?"
|
|
args = append(args, params.NumLimit, params.NumOffset)
|
|
}
|
|
|
|
return query, args
|
|
}
|
|
|
|
// fillPlaceHolders replaces all '?' placeholders in the SQL query with
|
|
// positional placeholders like $1, $2, etc. This is necessary for
|
|
// compatibility with Postgres.
|
|
func fillPlaceHolders(query string) string {
|
|
var (
|
|
sb strings.Builder
|
|
argNum = 1
|
|
)
|
|
|
|
for i := range len(query) {
|
|
if query[i] != '?' {
|
|
sb.WriteByte(query[i])
|
|
continue
|
|
}
|
|
|
|
sb.WriteString("$")
|
|
sb.WriteString(strconv.Itoa(argNum))
|
|
argNum++
|
|
}
|
|
|
|
return sb.String()
|
|
}
|