in registry/datastore/repository.go [1143:1236]
func tagsDetailPaginatedQuery(r *models.Repository, filters FilterParams) (string, []any, error) {
qb := NewQueryBuilder()
err := qb.Build(
`SELECT
t.name,
encode(m.digest, 'hex') AS digest,
encode(m.configuration_blob_digest, 'hex') AS config_digest,
mt.media_type,
m.total_size,
t.created_at,
t.updated_at,
GREATEST(t.created_at, t.updated_at) as published_at
FROM
tags AS t
JOIN manifests AS m ON m.top_level_namespace_id = t.top_level_namespace_id
AND m.repository_id = t.repository_id
AND m.id = t.manifest_id
JOIN media_types AS mt ON mt.id = m.media_type_id
WHERE
t.top_level_namespace_id = ?
AND t.repository_id = ?
`,
r.NamespaceID, r.ID,
)
if err != nil {
return "", nil, err
}
if filters.ExactName != "" {
// NOTE(prozlach): In the case when there is exact match requested,
// there is going to be only single entry in the response, or none. So
// there is no point in adding pagination and sorting keywords here.
err := qb.Build("AND t.name = ?", filters.ExactName)
if err != nil {
return "", nil, err
}
return qb.SQL(), qb.Params(), nil
}
// NOTE(prozlach): We handle both cases in this path - empty and not
// empty `Name` filter
err = qb.Build("AND t.name LIKE ?\n", sqlPartialMatch(filters.Name))
if err != nil {
return "", nil, err
}
// default to ascending order to keep backwards compatibility
if filters.SortOrder == "" {
filters.SortOrder = OrderAsc
}
if filters.OrderBy == "" {
filters.OrderBy = orderByName
}
switch {
case filters.LastEntry == "" && filters.BeforeEntry == "" && filters.PublishedAt == "":
// this should always return the first page up to filters.MaxEntries
if filters.OrderBy == "published_at" {
err = qb.Build(
fmt.Sprintf(`ORDER BY published_at %s, name %s LIMIT ?`, filters.SortOrder, filters.SortOrder),
filters.MaxEntries,
)
if err != nil {
return "", nil, err
}
} else {
err = qb.Build(
fmt.Sprintf(`ORDER BY name %s LIMIT ?`, filters.SortOrder),
filters.MaxEntries,
)
if err != nil {
return "", nil, err
}
}
case filters.LastEntry != "":
err := getLastEntryQuery(qb, filters)
if err != nil {
return "", nil, err
}
case filters.BeforeEntry != "":
err := getBeforeEntryQuery(qb, filters)
if err != nil {
return "", nil, err
}
case filters.PublishedAt != "":
err := getPublishedAtQuery(qb, filters)
if err != nil {
return "", nil, err
}
}
return qb.SQL(), qb.Params(), nil
}