aboutsummaryrefslogtreecommitdiffstats
path: root/models/packages/package_property.go
blob: acc05d8d5acd480985cabd7981f302fe38a7d206 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package packages

import (
	"context"

	"code.gitea.io/gitea/models/db"

	"xorm.io/builder"
)

func init() {
	db.RegisterModel(new(PackageProperty))
}

type PropertyType int64

const (
	// PropertyTypeVersion means the reference is a package version
	PropertyTypeVersion PropertyType = iota // 0
	// PropertyTypeFile means the reference is a package file
	PropertyTypeFile // 1
	// PropertyTypePackage means the reference is a package
	PropertyTypePackage // 2
)

// PackageProperty represents a property of a package, version or file
type PackageProperty struct {
	ID      int64        `xorm:"pk autoincr"`
	RefType PropertyType `xorm:"INDEX NOT NULL"`
	RefID   int64        `xorm:"INDEX NOT NULL"`
	Name    string       `xorm:"INDEX NOT NULL"`
	Value   string       `xorm:"LONGTEXT NOT NULL"`
}

// InsertProperty creates a property
func InsertProperty(ctx context.Context, refType PropertyType, refID int64, name, value string) (*PackageProperty, error) {
	pp := &PackageProperty{
		RefType: refType,
		RefID:   refID,
		Name:    name,
		Value:   value,
	}

	_, err := db.GetEngine(ctx).Insert(pp)
	return pp, err
}

// GetProperties gets all properties
func GetProperties(ctx context.Context, refType PropertyType, refID int64) ([]*PackageProperty, error) {
	pps := make([]*PackageProperty, 0, 10)
	return pps, db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ?", refType, refID).Find(&pps)
}

// GetPropertiesByName gets all properties with a specific name
func GetPropertiesByName(ctx context.Context, refType PropertyType, refID int64, name string) ([]*PackageProperty, error) {
	pps := make([]*PackageProperty, 0, 10)
	return pps, db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ? AND name = ?", refType, refID, name).Find(&pps)
}

// UpdateProperty updates a property
func UpdateProperty(ctx context.Context, pp *PackageProperty) error {
	_, err := db.GetEngine(ctx).ID(pp.ID).Update(pp)
	return err
}

func InsertOrUpdateProperty(ctx context.Context, refType PropertyType, refID int64, name, value string) error {
	pp := PackageProperty{RefType: refType, RefID: refID, Name: name}
	ok, err := db.GetEngine(ctx).Get(&pp)
	if err != nil {
		return err
	}
	if ok {
		_, err = db.GetEngine(ctx).Where("ref_type=? AND ref_id=? AND name=?", refType, refID, name).Cols("value").Update(&PackageProperty{Value: value})
		return err
	}
	_, err = InsertProperty(ctx, refType, refID, name, value)
	return err
}

// DeleteAllProperties deletes all properties of a ref
func DeleteAllProperties(ctx context.Context, refType PropertyType, refID int64) error {
	_, err := db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ?", refType, refID).Delete(&PackageProperty{})
	return err
}

// DeletePropertyByID deletes a property
func DeletePropertyByID(ctx context.Context, propertyID int64) error {
	_, err := db.GetEngine(ctx).ID(propertyID).Delete(&PackageProperty{})
	return err
}

// DeletePropertiesByName deletes properties by name
func DeletePropertiesByName(ctx context.Context, refType PropertyType, refID int64, name string) error {
	_, err := db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ? AND name = ?", refType, refID, name).Delete(&PackageProperty{})
	return err
}

type DistinctPropertyDependency struct {
	Name  string
	Value string
}

// GetDistinctPropertyValues returns all distinct property values for a given type.
// Optional: Search only in dependence of another property.
func GetDistinctPropertyValues(ctx context.Context, packageType Type, ownerID int64, refType PropertyType, propertyName string, dep *DistinctPropertyDependency) ([]string, error) {
	var cond builder.Cond = builder.Eq{
		"package_property.ref_type": refType,
		"package_property.name":     propertyName,
		"package.type":              packageType,
		"package.owner_id":          ownerID,
	}
	if dep != nil {
		innerCond := builder.
			Expr("pp.ref_id = package_property.ref_id").
			And(builder.Eq{
				"pp.ref_type": refType,
				"pp.name":     dep.Name,
				"pp.value":    dep.Value,
			})
		cond = cond.And(builder.Exists(builder.Select("pp.ref_id").From("package_property pp").Where(innerCond)))
	}

	values := make([]string, 0, 5)
	return values, db.GetEngine(ctx).
		Table("package_property").
		Distinct("package_property.value").
		Join("INNER", "package_file", "package_file.id = package_property.ref_id").
		Join("INNER", "package_version", "package_version.id = package_file.version_id").
		Join("INNER", "package", "package.id = package_version.package_id").
		Where(cond).
		Find(&values)
}