lxd/db/images.go
func (c *Cluster) ImageGet(project, fingerprint string, public bool, strictMatching bool) (int, *api.Image, error) {
	err := c.Transaction(func(tx *ClusterTx) error {
		enabled, err := tx.ProjectHasImages(project)
		if err != nil {
			return errors.Wrap(err, "Check if project has images")
		}
		if !enabled {
			project = "default"
		}
		return nil
	})
	if err != nil {
		return -1, nil, err
	}

	var create, expire, used, upload *time.Time // These hold the db-returned times

	// The object we'll actually return
	image := api.Image{}
	id := -1
	arch := -1

	// These two humongous things will be filled by the call to DbQueryRowScan
	outfmt := []interface{}{&id, &image.Fingerprint, &image.Filename,
		&image.Size, &image.Cached, &image.Public, &image.AutoUpdate, &arch,
		&create, &expire, &used, &upload}

	inargs := []interface{}{project}
	query := `
        SELECT
            images.id, fingerprint, filename, size, cached, public, auto_update, architecture,
            creation_date, expiry_date, last_use_date, upload_date
        FROM images
        JOIN projects ON projects.id = images.project_id
       WHERE projects.name = ?`
	if strictMatching {
		inargs = append(inargs, fingerprint)
		query += " AND fingerprint = ?"
	} else {
		inargs = append(inargs, fingerprint+"%")
		query += " AND fingerprint LIKE ?"
	}

	if public {
		query += " AND public=1"
	}

	err = dbQueryRowScan(c.db, query, inargs, outfmt)
	if err != nil {
		if err == sql.ErrNoRows {
			return -1, nil, ErrNoSuchObject
		}

		return -1, nil, err // Likely: there are no rows for this fingerprint
	}

	// Validate we only have a single match
	if !strictMatching {
		query = `
SELECT COUNT(images.id)
  FROM images
  JOIN projects ON projects.id = images.project_id
 WHERE projects.name = ?
   AND fingerprint LIKE ?
`
		count := 0
		outfmt := []interface{}{&count}

		err = dbQueryRowScan(c.db, query, inargs, outfmt)
		if err != nil {
			return -1, nil, err
		}

		if count > 1 {
			return -1, nil, fmt.Errorf("Partial fingerprint matches more than one image")
		}
	}

	err = c.imageFill(id, &image, create, expire, used, upload, arch)
	if err != nil {
		return -1, nil, errors.Wrapf(err, "Fill image details")
	}

	return id, &image, nil
}
func (c *Cluster) ImageGet(project, fingerprint string, public bool, strictMatching bool) (int, *api.Image, error) {
	err := c.Transaction(func(tx *ClusterTx) error {
		enabled, err := tx.ProjectHasImages(project)
		if err != nil {
			return errors.Wrap(err, "Check if project has images")
		}
		if !enabled {
			project = "default"
		}
		return nil
	})
	if err != nil {
		return -1, nil, err
	}

	var create, expire, used, upload *time.Time // These hold the db-returned times

	// The object we'll actually return
	image := api.Image{}
	id := -1
	arch := -1

	// These two humongous things will be filled by the call to DbQueryRowScan
	outfmt := []interface{}{&id, &image.Fingerprint, &image.Filename,
		&image.Size, &image.Cached, &image.Public, &image.AutoUpdate, &arch,
		&create, &expire, &used, &upload}

	inargs := []interface{}{project}
	query := `
        SELECT
            images.id, fingerprint, filename, size, cached, public, auto_update, architecture,
            creation_date, expiry_date, last_use_date, upload_date
        FROM images
        JOIN projects ON projects.id = images.project_id
       WHERE projects.name = ?`
	if strictMatching {
		inargs = append(inargs, fingerprint)
		query += " AND fingerprint = ?"
	} else {
		inargs = append(inargs, fingerprint+"%")
		query += " AND fingerprint LIKE ?"
	}

	if public {
		query += " AND public=1"
	}

	err = dbQueryRowScan(c.db, query, inargs, outfmt)
	if err != nil {
		if err == sql.ErrNoRows {
			return -1, nil, ErrNoSuchObject
		}

		return -1, nil, err // Likely: there are no rows for this fingerprint
	}

	// Validate we only have a single match
	if !strictMatching {
		query = `
SELECT COUNT(images.id)
  FROM images
  JOIN projects ON projects.id = images.project_id
 WHERE projects.name = ?
   AND fingerprint LIKE ?
`
		count := 0
		outfmt := []interface{}{&count}

		err = dbQueryRowScan(c.db, query, inargs, outfmt)
		if err != nil {
			return -1, nil, err
		}

		if count > 1 {
			return -1, nil, fmt.Errorf("Partial fingerprint matches more than one image")
		}
	}

	err = c.imageFill(id, &image, create, expire, used, upload, arch)
	if err != nil {
		return -1, nil, errors.Wrapf(err, "Fill image details")
	}

	return id, &image, nil
}
// ImageGet gets an Image object from the database.
// If strictMatching is false, The fingerprint argument will be queried with a LIKE query, means you can
// pass a shortform and will get the full fingerprint.
// There can never be more than one image with a given fingerprint, as it is
// enforced by a UNIQUE constraint in the schema.