306 lines
9.4 KiB
Go
306 lines
9.4 KiB
Go
/*
|
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
|
*
|
|
* This work is published and licensed under a Creative Commons
|
|
* Attribution-NonCommercial-NoDerivatives 4.0 International License.
|
|
*
|
|
* Distribution of this work is permitted, but commercial use and
|
|
* modifications are strictly prohibited.
|
|
*/
|
|
package maindb
|
|
|
|
import (
|
|
"context"
|
|
|
|
"mstore/pkg/descr"
|
|
)
|
|
|
|
func (db *Database) InsertManifest(ctx context.Context, manifest *descr.Manifest) error {
|
|
var err error
|
|
var request string
|
|
request = `INSERT INTO manifests(id, name, reference, contentType, payload, digest,
|
|
created_at, updated_at, created_by, updated_by, architecture, os, variant)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`
|
|
_, err = db.db.Exec(request, manifest.ID, manifest.Name, manifest.Reference,
|
|
manifest.ContentType, manifest.Payload, manifest.Digest,
|
|
manifest.CreatedAt, manifest.UpdatedAt,
|
|
manifest.CreatedBy, manifest.UpdatedBy,
|
|
manifest.Architecture, manifest.OS, manifest.Variant)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (db *Database) InsertManifests(ctx context.Context, manifests []*descr.Manifest) error {
|
|
var err error
|
|
|
|
// Begin Tx
|
|
tx, err := db.db.BeginTx(ctx, nil)
|
|
for _, manifest := range manifests {
|
|
var request string
|
|
request = `INSERT INTO manifests(id, name, reference, contentType, payload, digest,
|
|
created_at, updated_at, created_by, updated_by,
|
|
architecture, os, variant)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`
|
|
_, err = tx.Exec(request, manifest.ID, manifest.Name, manifest.Reference,
|
|
manifest.ContentType, manifest.Payload, manifest.Digest,
|
|
manifest.CreatedAt, manifest.UpdatedAt,
|
|
manifest.CreatedBy, manifest.UpdatedBy,
|
|
manifest.Architecture, manifest.OS, manifest.Variant)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
// Commit
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (db *Database) UpdateManifest(ctx context.Context, manifest *descr.Manifest) error {
|
|
var err error
|
|
var request string
|
|
// Manifest
|
|
request = `UPDATE manifests SET contentType = $1, payload = $2, digest = $3, updated_at = $4
|
|
WHERE name = $5 AND reference = $6, architecture = $7, os = $8, variant = $9`
|
|
_, err = db.db.Exec(request, manifest.ContentType, manifest.Payload, manifest.Digest,
|
|
manifest.UpdatedAt, manifest.Name, manifest.Reference,
|
|
manifest.Architecture, manifest.OS, manifest.Variant)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (db *Database) InsertManifestWithLayers(ctx context.Context, manifest *descr.Manifest, layers []descr.Blob) error {
|
|
var err error
|
|
var request string
|
|
|
|
// Begin Tx
|
|
tx, err := db.db.BeginTx(ctx, nil)
|
|
// Manifest
|
|
request = `
|
|
INSERT INTO manifests(id, name, reference, contentType, payload, digest,
|
|
created_at, updated_at, created_by, updated_by, architecture, os, variant)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);`
|
|
_, err = tx.Exec(request, manifest.ID, manifest.Name, manifest.Reference,
|
|
manifest.ContentType, manifest.Payload, manifest.Digest,
|
|
manifest.CreatedAt, manifest.UpdatedAt,
|
|
manifest.CreatedBy, manifest.UpdatedBy,
|
|
manifest.Architecture, manifest.OS, manifest.Variant)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Layers
|
|
for _, layer := range layers {
|
|
request = `
|
|
INSERT INTO blobs(id, name, reference, mediaType, digest, size,
|
|
created_at, updated_at, created_by, updated_by)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`
|
|
_, err = tx.Exec(request,
|
|
layer.ID, layer.Name, layer.Reference, layer.MediaType,
|
|
layer.Digest, layer.Size,
|
|
layer.CreatedAt, layer.UpdatedAt,
|
|
layer.CreatedBy, layer.UpdatedBy)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
// Commit
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// TODO: tx.Rollback()
|
|
return err
|
|
}
|
|
|
|
func (db *Database) UpdateManifestWithBlobs(ctx context.Context, manifest *descr.Manifest,
|
|
newLayers []descr.Blob, oldLayers []descr.Blob) error {
|
|
var err error
|
|
var request string
|
|
|
|
// Begin Tx
|
|
tx, err := db.db.BeginTx(ctx, nil)
|
|
// TODO: tx.Rollback()
|
|
|
|
// Manifest
|
|
request = `UPDATE manifests SET contentType = $1, payload = $2, digest = $3, updated_at = $4, updated_by = $5
|
|
WHERE name = $6 AND reference = $7, architecture = $8, os = $9, variant = $10`
|
|
_, err = tx.Exec(request, manifest.ContentType, manifest.Payload, manifest.Digest,
|
|
manifest.UpdatedAt, manifest.UpdatedBy,
|
|
manifest.Name, manifest.Reference,
|
|
manifest.Architecture, manifest.OS, manifest.Variant)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// New layers
|
|
for _, layer := range newLayers {
|
|
request = `INSERT INTO blobs(id, name, reference, mediaType, digest, size,
|
|
created_at, updated_at, created_by, updated_by)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`
|
|
_, err = tx.Exec(request, layer.ID, layer.Name, layer.Reference, layer.MediaType,
|
|
layer.Digest, layer.Size, layer.CreatedAt, layer.UpdatedAt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
// Old layers
|
|
for _, layer := range oldLayers {
|
|
request = `DELETE FROM blobs WHERE name == $1 AND reference == $2 AND digest == $3`
|
|
_, err = tx.Exec(request, layer.Name, layer.Reference, layer.Digest)
|
|
}
|
|
// Commit
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (db *Database) ManifestExistsByReference(ctx context.Context, name, reference string) (bool, error) {
|
|
var err error
|
|
var count int
|
|
var exists bool
|
|
request := `SELECT count(id) AS count FROM manifests WHERE name = $1 AND reference = $2 LIMIT 1`
|
|
err = db.db.Get(&count, request, name, reference)
|
|
if err != nil {
|
|
return exists, err
|
|
}
|
|
if count > 0 {
|
|
exists = true
|
|
}
|
|
return exists, err
|
|
}
|
|
|
|
func (db *Database) ManifestExistsByDigest(ctx context.Context, name, digest string) (bool, error) {
|
|
var err error
|
|
var count int
|
|
var exists bool
|
|
request := `SELECT count(id) AS count FROM manifests WHERE name = $1 AND digest = $2 LIMIT 1`
|
|
err = db.db.Get(&count, request, name, digest)
|
|
if err != nil {
|
|
return exists, err
|
|
}
|
|
if count > 0 {
|
|
exists = true
|
|
}
|
|
return exists, err
|
|
}
|
|
|
|
func (db *Database) GetManifestByDigest(ctx context.Context, name, digest string) (bool, descr.Manifest, error) {
|
|
var err error
|
|
manifest := descr.Manifest{}
|
|
manifests := make([]descr.Manifest, 0)
|
|
exists := false
|
|
request := `SELECT * FROM manifests WHERE name = $1 AND digest = $2 LIMIT 1`
|
|
err = db.db.Select(&manifests, request, name, digest)
|
|
if err != nil {
|
|
return exists, manifest, err
|
|
}
|
|
if len(manifests) > 0 {
|
|
exists = true
|
|
manifest = manifests[0]
|
|
}
|
|
return exists, manifest, err
|
|
}
|
|
|
|
func (db *Database) GetManifestsByReference(ctx context.Context, name, reference string) (bool, []descr.Manifest, error) {
|
|
var err error
|
|
exists := false
|
|
manifests := make([]descr.Manifest, 0)
|
|
request := `SELECT * FROM manifests WHERE name = $1 AND reference = $2 LIMIT 1`
|
|
err = db.db.Select(&manifests, request, name, reference)
|
|
if err != nil {
|
|
return exists, manifests, err
|
|
}
|
|
|
|
if len(manifests) > 0 {
|
|
exists = true
|
|
}
|
|
return exists, manifests, err
|
|
}
|
|
|
|
func (db *Database) GetManifestsByReferenceArchitecture(ctx context.Context, name, reference, architecture, os, variant string) (bool, descr.Manifest, error) {
|
|
var err error
|
|
exists := false
|
|
manifest := descr.Manifest{}
|
|
manifests := make([]descr.Manifest, 0)
|
|
request := `SELECT * FROM manifests WHERE name = $1 AND reference = $2
|
|
AND architecture = $3 AND os = $4 AND variant = $5 LIMIT 1000`
|
|
err = db.db.Select(&manifests, request, name, reference, architecture, os, variant)
|
|
if err != nil {
|
|
return exists, manifest, err
|
|
}
|
|
|
|
if len(manifests) > 0 {
|
|
manifest = manifests[0]
|
|
exists = true
|
|
}
|
|
return exists, manifest, err
|
|
}
|
|
|
|
func (db *Database) ListManifestsByName(ctx context.Context, name string) ([]descr.Manifest, error) {
|
|
var err error
|
|
manifests := make([]descr.Manifest, 0)
|
|
request := `SELECT id, name, reference, contentType, payload FROM manifests WHERE name = $1`
|
|
err = db.db.Select(&manifests, request, name)
|
|
if err != nil {
|
|
return manifests, err
|
|
}
|
|
return manifests, err
|
|
}
|
|
|
|
func (db *Database) ListAllManifests(ctx context.Context) ([]descr.Manifest, error) {
|
|
var err error
|
|
manifests := make([]descr.Manifest, 0)
|
|
request := `SELECT * FROM manifests`
|
|
err = db.db.Select(&manifests, request)
|
|
if err != nil {
|
|
return manifests, err
|
|
}
|
|
return manifests, err
|
|
}
|
|
|
|
func (db *Database) GetReferer(ctx context.Context, name, digest string) ([]descr.Manifest, error) {
|
|
var err error
|
|
manifests := make([]descr.Manifest, 0)
|
|
request := `SELECT * FROM manifests WHERE name = $1, digest = $2`
|
|
err = db.db.Select(&manifests, request, name, digest)
|
|
if err != nil {
|
|
return manifests, err
|
|
}
|
|
return manifests, err
|
|
}
|
|
|
|
func (db *Database) DeleteManifest(ctx context.Context, name, reference string) error {
|
|
var err error
|
|
var request string
|
|
|
|
// Begin Tx
|
|
tx, err := db.db.BeginTx(ctx, nil)
|
|
// TODO: tx.Rollback()
|
|
|
|
// Blobs
|
|
request = `DELETE FROM blobs WHERE name = $1 AND reference = $2`
|
|
_, err = tx.Exec(request, name, reference)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Manifest
|
|
request = `DELETE FROM manifests WHERE name = $1 AND reference = $2`
|
|
_, err = tx.Exec(request, name, reference)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Commit
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return err
|
|
}
|