Merge pull request #10886 from ywk253100/200228_transaction

Fix transaction issue
This commit is contained in:
Wenkai Yin(尹文开) 2020-03-04 08:53:35 +08:00 committed by GitHub
commit 3e29d4cd3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 230 additions and 92 deletions

View File

@ -27,6 +27,7 @@ import (
"github.com/goharbor/harbor/src/api/artifact/descriptor" "github.com/goharbor/harbor/src/api/artifact/descriptor"
"github.com/goharbor/harbor/src/api/tag" "github.com/goharbor/harbor/src/api/tag"
"github.com/goharbor/harbor/src/internal" "github.com/goharbor/harbor/src/internal"
"github.com/goharbor/harbor/src/internal/orm"
"github.com/goharbor/harbor/src/pkg/artifactrash" "github.com/goharbor/harbor/src/pkg/artifactrash"
"github.com/goharbor/harbor/src/pkg/artifactrash/model" "github.com/goharbor/harbor/src/pkg/artifactrash/model"
"github.com/goharbor/harbor/src/pkg/blob" "github.com/goharbor/harbor/src/pkg/blob"
@ -175,20 +176,30 @@ func (c *controller) ensureArtifact(ctx context.Context, repository, digest stri
artifact.Type = descriptor.GetArtifactType(artifact.MediaType) artifact.Type = descriptor.GetArtifactType(artifact.MediaType)
// create it // create it
// use orm.WithTransaction here to avoid the issue:
// https://www.postgresql.org/message-id/002e01c04da9%24a8f95c20%2425efe6c1%40lasting.ro
created := false
if err = orm.WithTransaction(func(ctx context.Context) error {
id, err := c.artMgr.Create(ctx, artifact) id, err := c.artMgr.Create(ctx, artifact)
if err != nil { if err != nil {
// if got conflict error, try to get the artifact again // if got conflict error, try to get the artifact again
if ierror.IsConflictErr(err) { if ierror.IsConflictErr(err) {
art, err = c.artMgr.GetByDigest(ctx, repository, digest) var e error
if err == nil { artifact, e = c.artMgr.GetByDigest(ctx, repository, digest)
return false, art, nil if e != nil {
err = e
} }
return false, nil, err
} }
return false, nil, err return err
} }
created = true
artifact.ID = id artifact.ID = id
return true, artifact, nil return nil
})(ctx); err != nil && !ierror.IsConflictErr(err) {
return false, nil, err
}
return created, artifact, nil
} }
func (c *controller) Count(ctx context.Context, query *q.Query) (int64, error) { func (c *controller) Count(ctx context.Context, query *q.Query) (int64, error) {
@ -338,15 +349,20 @@ func (c *controller) deleteDeeply(ctx context.Context, id int64, isRoot bool) er
return err return err
} }
// use orm.WithTransaction here to avoid the issue:
// https://www.postgresql.org/message-id/002e01c04da9%24a8f95c20%2425efe6c1%40lasting.ro
if err = orm.WithTransaction(func(ctx context.Context) error {
_, err = c.artrashMgr.Create(ctx, &model.ArtifactTrash{ _, err = c.artrashMgr.Create(ctx, &model.ArtifactTrash{
MediaType: art.MediaType, MediaType: art.MediaType,
ManifestMediaType: art.ManifestMediaType, ManifestMediaType: art.ManifestMediaType,
RepositoryName: art.RepositoryName, RepositoryName: art.RepositoryName,
Digest: art.Digest, Digest: art.Digest,
}) })
if err != nil && !ierror.IsErr(err, ierror.ConflictCode) { return err
})(ctx); err != nil && !ierror.IsErr(err, ierror.ConflictCode) {
return err return err
} }
// TODO fire delete artifact event // TODO fire delete artifact event
return nil return nil

View File

@ -25,10 +25,12 @@ import (
"github.com/goharbor/harbor/src/common/models" "github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/internal" "github.com/goharbor/harbor/src/internal"
ierror "github.com/goharbor/harbor/src/internal/error" ierror "github.com/goharbor/harbor/src/internal/error"
"github.com/goharbor/harbor/src/internal/orm"
"github.com/goharbor/harbor/src/pkg/artifact" "github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/q" "github.com/goharbor/harbor/src/pkg/q"
model_tag "github.com/goharbor/harbor/src/pkg/tag/model/tag" model_tag "github.com/goharbor/harbor/src/pkg/tag/model/tag"
tagtesting "github.com/goharbor/harbor/src/testing/api/tag" tagtesting "github.com/goharbor/harbor/src/testing/api/tag"
ormtesting "github.com/goharbor/harbor/src/testing/lib/orm"
arttesting "github.com/goharbor/harbor/src/testing/pkg/artifact" arttesting "github.com/goharbor/harbor/src/testing/pkg/artifact"
artrashtesting "github.com/goharbor/harbor/src/testing/pkg/artifactrash" artrashtesting "github.com/goharbor/harbor/src/testing/pkg/artifactrash"
"github.com/goharbor/harbor/src/testing/pkg/blob" "github.com/goharbor/harbor/src/testing/pkg/blob"
@ -162,7 +164,7 @@ func (c *controllerTestSuite) TestEnsureArtifact() {
c.artMgr.On("GetByDigest").Return(&artifact.Artifact{ c.artMgr.On("GetByDigest").Return(&artifact.Artifact{
ID: 1, ID: 1,
}, nil) }, nil)
created, art, err := c.ctl.ensureArtifact(nil, "library/hello-world", digest) created, art, err := c.ctl.ensureArtifact(orm.NewContext(nil, &ormtesting.FakeOrmer{}), "library/hello-world", digest)
c.Require().Nil(err) c.Require().Nil(err)
c.False(created) c.False(created)
c.Equal(int64(1), art.ID) c.Equal(int64(1), art.ID)
@ -177,7 +179,7 @@ func (c *controllerTestSuite) TestEnsureArtifact() {
c.artMgr.On("GetByDigest").Return(nil, ierror.NotFoundError(nil)) c.artMgr.On("GetByDigest").Return(nil, ierror.NotFoundError(nil))
c.artMgr.On("Create").Return(1, nil) c.artMgr.On("Create").Return(1, nil)
c.abstractor.On("AbstractMetadata").Return(nil) c.abstractor.On("AbstractMetadata").Return(nil)
created, art, err = c.ctl.ensureArtifact(nil, "library/hello-world", digest) created, art, err = c.ctl.ensureArtifact(orm.NewContext(nil, &ormtesting.FakeOrmer{}), "library/hello-world", digest)
c.Require().Nil(err) c.Require().Nil(err)
c.True(created) c.True(created)
c.Equal(int64(1), art.ID) c.Equal(int64(1), art.ID)
@ -194,7 +196,7 @@ func (c *controllerTestSuite) TestEnsure() {
c.artMgr.On("Create").Return(1, nil) c.artMgr.On("Create").Return(1, nil)
c.abstractor.On("AbstractMetadata").Return(nil) c.abstractor.On("AbstractMetadata").Return(nil)
c.tagCtl.On("Ensure").Return(nil) c.tagCtl.On("Ensure").Return(nil)
_, id, err := c.ctl.Ensure(nil, "library/hello-world", digest, "latest") _, id, err := c.ctl.Ensure(orm.NewContext(nil, &ormtesting.FakeOrmer{}), "library/hello-world", digest, "latest")
c.Require().Nil(err) c.Require().Nil(err)
c.repoMgr.AssertExpectations(c.T()) c.repoMgr.AssertExpectations(c.T())
c.artMgr.AssertExpectations(c.T()) c.artMgr.AssertExpectations(c.T())
@ -370,7 +372,7 @@ func (c *controllerTestSuite) TestGetByReference() {
func (c *controllerTestSuite) TestDeleteDeeply() { func (c *controllerTestSuite) TestDeleteDeeply() {
// root artifact and doesn't exist // root artifact and doesn't exist
c.artMgr.On("Get").Return(nil, ierror.NotFoundError(nil)) c.artMgr.On("Get").Return(nil, ierror.NotFoundError(nil))
err := c.ctl.deleteDeeply(nil, 1, true) err := c.ctl.deleteDeeply(orm.NewContext(nil, &ormtesting.FakeOrmer{}), 1, true)
c.Require().NotNil(err) c.Require().NotNil(err)
c.Assert().True(ierror.IsErr(err, ierror.NotFoundCode)) c.Assert().True(ierror.IsErr(err, ierror.NotFoundCode))
@ -379,7 +381,7 @@ func (c *controllerTestSuite) TestDeleteDeeply() {
// child artifact and doesn't exist // child artifact and doesn't exist
c.artMgr.On("Get").Return(nil, ierror.NotFoundError(nil)) c.artMgr.On("Get").Return(nil, ierror.NotFoundError(nil))
err = c.ctl.deleteDeeply(nil, 1, false) err = c.ctl.deleteDeeply(orm.NewContext(nil, &ormtesting.FakeOrmer{}), 1, false)
c.Require().Nil(err) c.Require().Nil(err)
// reset the mock // reset the mock
@ -397,7 +399,7 @@ func (c *controllerTestSuite) TestDeleteDeeply() {
}, nil) }, nil)
c.repoMgr.On("Get").Return(&models.RepoRecord{}, nil) c.repoMgr.On("Get").Return(&models.RepoRecord{}, nil)
c.artrashMgr.On("Create").Return(0, nil) c.artrashMgr.On("Create").Return(0, nil)
err = c.ctl.deleteDeeply(nil, 1, false) err = c.ctl.deleteDeeply(orm.NewContext(nil, &ormtesting.FakeOrmer{}), 1, false)
c.Require().Nil(err) c.Require().Nil(err)
// reset the mock // reset the mock
@ -412,7 +414,7 @@ func (c *controllerTestSuite) TestDeleteDeeply() {
ID: 1, ID: 1,
}, },
}, nil) }, nil)
err = c.ctl.deleteDeeply(nil, 1, true) err = c.ctl.deleteDeeply(orm.NewContext(nil, &ormtesting.FakeOrmer{}), 1, true)
c.Require().NotNil(err) c.Require().NotNil(err)
// reset the mock // reset the mock
@ -429,24 +431,6 @@ func (c *controllerTestSuite) TestDeleteDeeply() {
}, nil) }, nil)
err = c.ctl.deleteDeeply(nil, 1, false) err = c.ctl.deleteDeeply(nil, 1, false)
c.Require().Nil(err) c.Require().Nil(err)
// reset the mock
c.SetupTest()
// root artifact is referenced by other artifacts
c.artMgr.On("Get").Return(&artifact.Artifact{ID: 1}, nil)
c.tagCtl.On("List").Return(nil, nil)
c.blobMgr.On("List", nil, mock.AnythingOfType("models.ListParams")).Return(nil, nil).Once()
c.blobMgr.On("CleanupAssociationsForProject", nil, int64(0), mock.AnythingOfType("[]*models.Blob")).Return(nil).Once()
c.repoMgr.On("Get").Return(&models.RepoRecord{}, nil)
c.artMgr.On("ListReferences").Return(nil, nil)
c.tagCtl.On("DeleteOfArtifact").Return(nil)
c.artMgr.On("Delete").Return(nil)
c.labelMgr.On("RemoveAllFrom").Return(nil)
c.artrashMgr.On("Create").Return(0, nil)
c.tagCtl.On("DeleteTags").Return(nil)
err = c.ctl.deleteDeeply(nil, 1, true)
c.Require().Nil(err)
} }
func (c *controllerTestSuite) TestCopy() { func (c *controllerTestSuite) TestCopy() {
@ -476,7 +460,7 @@ func (c *controllerTestSuite) TestCopy() {
c.artMgr.On("Create").Return(1, nil) c.artMgr.On("Create").Return(1, nil)
c.regCli.On("Copy").Return(nil) c.regCli.On("Copy").Return(nil)
c.tagCtl.On("Ensure").Return(nil) c.tagCtl.On("Ensure").Return(nil)
_, err := c.ctl.Copy(nil, "library/hello-world", "latest", "library/hello-world2") _, err := c.ctl.Copy(orm.NewContext(nil, &ormtesting.FakeOrmer{}), "library/hello-world", "latest", "library/hello-world2")
c.Require().Nil(err) c.Require().Nil(err)
} }

View File

@ -20,6 +20,7 @@ import (
"github.com/goharbor/harbor/src/common/models" "github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/common/utils" "github.com/goharbor/harbor/src/common/utils"
ierror "github.com/goharbor/harbor/src/internal/error" ierror "github.com/goharbor/harbor/src/internal/error"
"github.com/goharbor/harbor/src/internal/orm"
"github.com/goharbor/harbor/src/pkg/project" "github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/q" "github.com/goharbor/harbor/src/pkg/q"
"github.com/goharbor/harbor/src/pkg/repository" "github.com/goharbor/harbor/src/pkg/repository"
@ -66,18 +67,15 @@ type controller struct {
} }
func (c *controller) Ensure(ctx context.Context, name string) (bool, int64, error) { func (c *controller) Ensure(ctx context.Context, name string) (bool, int64, error) {
query := &q.Query{
Keywords: map[string]interface{}{
"name": name,
},
}
repositories, err := c.repoMgr.List(ctx, query)
if err != nil {
return false, 0, err
}
// the repository already exists, return directly // the repository already exists, return directly
if len(repositories) > 0 { repository, err := c.repoMgr.GetByName(ctx, name)
return false, repositories[0].RepositoryID, nil if err == nil {
return false, repository.RepositoryID, nil
}
// got other error when get the repository, return the error
if !ierror.IsErr(err, ierror.NotFoundCode) {
return false, 0, err
} }
// the repository doesn't exist, create it first // the repository doesn't exist, create it first
@ -86,24 +84,38 @@ func (c *controller) Ensure(ctx context.Context, name string) (bool, int64, erro
if err != nil { if err != nil {
return false, 0, err return false, 0, err
} }
id, err := c.repoMgr.Create(ctx, &models.RepoRecord{
var (
created bool
id int64
)
// use orm.WithTransaction here to avoid the issue:
// https://www.postgresql.org/message-id/002e01c04da9%24a8f95c20%2425efe6c1%40lasting.ro
if err = orm.WithTransaction(func(ctx context.Context) error {
id, err = c.repoMgr.Create(ctx, &models.RepoRecord{
ProjectID: project.ProjectID, ProjectID: project.ProjectID,
Name: name, Name: name,
}) })
if err != nil { if err != nil {
// if got conflict error, try to get again // if got conflict error, try to get again
if ierror.IsConflictErr(err) { if ierror.IsConflictErr(err) {
repositories, err = c.repoMgr.List(ctx, query) var e error
if err != nil { repository, e = c.repoMgr.GetByName(ctx, name)
if e != nil {
err = e
} else {
id = repository.RepositoryID
}
}
return err
}
created = true
return nil
})(ctx); err != nil && !ierror.IsConflictErr(err) {
return false, 0, err return false, 0, err
} }
if len(repositories) > 0 {
return false, repositories[0].RepositoryID, nil return created, id, nil
}
}
return false, 0, err
}
return true, id, nil
} }
func (c *controller) Count(ctx context.Context, query *q.Query) (int64, error) { func (c *controller) Count(ctx context.Context, query *q.Query) (int64, error) {
@ -123,7 +135,6 @@ func (c *controller) GetByName(ctx context.Context, name string) (*models.RepoRe
} }
func (c *controller) Delete(ctx context.Context, id int64) error { func (c *controller) Delete(ctx context.Context, id int64) error {
// TODO auth
// TODO how to make sure the logic included by middlewares(immutable, readonly, quota, etc) // TODO how to make sure the logic included by middlewares(immutable, readonly, quota, etc)
// TODO is covered when deleting the artifacts of the repository // TODO is covered when deleting the artifacts of the repository
artifacts, err := c.artCtl.List(ctx, &q.Query{ artifacts, err := c.artCtl.List(ctx, &q.Query{

View File

@ -15,15 +15,17 @@
package repository package repository
import ( import (
"testing"
"github.com/goharbor/harbor/src/api/artifact" "github.com/goharbor/harbor/src/api/artifact"
"github.com/goharbor/harbor/src/common/models" "github.com/goharbor/harbor/src/common/models"
ierror "github.com/goharbor/harbor/src/internal/error"
"github.com/goharbor/harbor/src/internal/orm"
artifacttesting "github.com/goharbor/harbor/src/testing/api/artifact" artifacttesting "github.com/goharbor/harbor/src/testing/api/artifact"
ormtesting "github.com/goharbor/harbor/src/testing/lib/orm"
"github.com/goharbor/harbor/src/testing/mock" "github.com/goharbor/harbor/src/testing/mock"
"github.com/goharbor/harbor/src/testing/pkg/project" "github.com/goharbor/harbor/src/testing/pkg/project"
"github.com/goharbor/harbor/src/testing/pkg/repository" "github.com/goharbor/harbor/src/testing/pkg/repository"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"testing"
) )
type controllerTestSuite struct { type controllerTestSuite struct {
@ -47,12 +49,10 @@ func (c *controllerTestSuite) SetupTest() {
func (c *controllerTestSuite) TestEnsure() { func (c *controllerTestSuite) TestEnsure() {
// already exists // already exists
c.repoMgr.On("List").Return([]*models.RepoRecord{ c.repoMgr.On("GetByName").Return(&models.RepoRecord{
{
RepositoryID: 1, RepositoryID: 1,
ProjectID: 1, ProjectID: 1,
Name: "library/hello-world", Name: "library/hello-world",
},
}, nil) }, nil)
created, id, err := c.ctl.Ensure(nil, "library/hello-world") created, id, err := c.ctl.Ensure(nil, "library/hello-world")
c.Require().Nil(err) c.Require().Nil(err)
@ -64,12 +64,12 @@ func (c *controllerTestSuite) TestEnsure() {
c.SetupTest() c.SetupTest()
// doesn't exist // doesn't exist
c.repoMgr.On("List").Return([]*models.RepoRecord{}, nil) c.repoMgr.On("GetByName").Return(nil, ierror.NotFoundError(nil))
c.proMgr.On("Get", "library").Return(&models.Project{ c.proMgr.On("Get", "library").Return(&models.Project{
ProjectID: 1, ProjectID: 1,
}, nil) }, nil)
c.repoMgr.On("Create").Return(1, nil) c.repoMgr.On("Create").Return(1, nil)
created, id, err = c.ctl.Ensure(nil, "library/hello-world") created, id, err = c.ctl.Ensure(orm.NewContext(nil, &ormtesting.FakeOrmer{}), "library/hello-world")
c.Require().Nil(err) c.Require().Nil(err)
c.repoMgr.AssertExpectations(c.T()) c.repoMgr.AssertExpectations(c.T())
c.proMgr.AssertExpectations(c.T()) c.proMgr.AssertExpectations(c.T())

View File

@ -5,6 +5,7 @@ import (
"github.com/goharbor/harbor/src/common/utils" "github.com/goharbor/harbor/src/common/utils"
"github.com/goharbor/harbor/src/common/utils/log" "github.com/goharbor/harbor/src/common/utils/log"
ierror "github.com/goharbor/harbor/src/internal/error" ierror "github.com/goharbor/harbor/src/internal/error"
"github.com/goharbor/harbor/src/internal/orm"
"github.com/goharbor/harbor/src/pkg/artifact" "github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/artifactselector" "github.com/goharbor/harbor/src/pkg/artifactselector"
"github.com/goharbor/harbor/src/pkg/immutabletag/match" "github.com/goharbor/harbor/src/pkg/immutabletag/match"
@ -88,18 +89,23 @@ func (c *controller) Ensure(ctx context.Context, repositoryID, artifactID int64,
tag.PushTime = time.Now() tag.PushTime = time.Now()
return c.Update(ctx, tag, "ArtifactID", "PushTime") return c.Update(ctx, tag, "ArtifactID", "PushTime")
} }
// the tag doesn't exist under the repository, create it // the tag doesn't exist under the repository, create it
// use orm.WithTransaction here to avoid the issue:
// https://www.postgresql.org/message-id/002e01c04da9%24a8f95c20%2425efe6c1%40lasting.ro
if err = orm.WithTransaction(func(ctx context.Context) error {
tag := &Tag{} tag := &Tag{}
tag.RepositoryID = repositoryID tag.RepositoryID = repositoryID
tag.ArtifactID = artifactID tag.ArtifactID = artifactID
tag.Name = name tag.Name = name
tag.PushTime = time.Now() tag.PushTime = time.Now()
_, err = c.Create(ctx, tag) _, err = c.Create(ctx, tag)
// ignore the conflict error
if err != nil && ierror.IsConflictErr(err) {
return nil
}
return err return err
})(ctx); err != nil && !ierror.IsConflictErr(err) {
return err
}
return nil
} }
// Count ... // Count ...

View File

@ -4,8 +4,10 @@ import (
"github.com/goharbor/harbor/src/common" "github.com/goharbor/harbor/src/common"
coreConfig "github.com/goharbor/harbor/src/core/config" coreConfig "github.com/goharbor/harbor/src/core/config"
ierror "github.com/goharbor/harbor/src/internal/error" ierror "github.com/goharbor/harbor/src/internal/error"
"github.com/goharbor/harbor/src/internal/orm"
pkg_artifact "github.com/goharbor/harbor/src/pkg/artifact" pkg_artifact "github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/tag/model/tag" "github.com/goharbor/harbor/src/pkg/tag/model/tag"
ormtesting "github.com/goharbor/harbor/src/testing/lib/orm"
"github.com/goharbor/harbor/src/testing/pkg/artifact" "github.com/goharbor/harbor/src/testing/pkg/artifact"
immutesting "github.com/goharbor/harbor/src/testing/pkg/immutabletag" immutesting "github.com/goharbor/harbor/src/testing/pkg/immutabletag"
"github.com/goharbor/harbor/src/testing/pkg/repository" "github.com/goharbor/harbor/src/testing/pkg/repository"
@ -55,7 +57,7 @@ func (c *controllerTestSuite) TestEnsureTag() {
ID: 1, ID: 1,
}, nil) }, nil)
c.immutableMtr.On("Match").Return(false, nil) c.immutableMtr.On("Match").Return(false, nil)
err := c.ctl.Ensure(nil, 1, 1, "latest") err := c.ctl.Ensure(orm.NewContext(nil, &ormtesting.FakeOrmer{}), 1, 1, "latest")
c.Require().Nil(err) c.Require().Nil(err)
c.tagMgr.AssertExpectations(c.T()) c.tagMgr.AssertExpectations(c.T())
@ -76,7 +78,7 @@ func (c *controllerTestSuite) TestEnsureTag() {
ID: 1, ID: 1,
}, nil) }, nil)
c.immutableMtr.On("Match").Return(false, nil) c.immutableMtr.On("Match").Return(false, nil)
err = c.ctl.Ensure(nil, 1, 1, "latest") err = c.ctl.Ensure(orm.NewContext(nil, &ormtesting.FakeOrmer{}), 1, 1, "latest")
c.Require().Nil(err) c.Require().Nil(err)
c.tagMgr.AssertExpectations(c.T()) c.tagMgr.AssertExpectations(c.T())
@ -90,7 +92,7 @@ func (c *controllerTestSuite) TestEnsureTag() {
ID: 1, ID: 1,
}, nil) }, nil)
c.immutableMtr.On("Match").Return(false, nil) c.immutableMtr.On("Match").Return(false, nil)
err = c.ctl.Ensure(nil, 1, 1, "latest") err = c.ctl.Ensure(orm.NewContext(nil, &ormtesting.FakeOrmer{}), 1, 1, "latest")
c.Require().Nil(err) c.Require().Nil(err)
c.tagMgr.AssertExpectations(c.T()) c.tagMgr.AssertExpectations(c.T())
} }

119
src/testing/lib/orm/orm.go Normal file
View File

@ -0,0 +1,119 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package orm
import (
"context"
"database/sql"
"github.com/astaxie/beego/orm"
)
// FakeOrmer ...
type FakeOrmer struct{}
// Read ...
func (f *FakeOrmer) Read(md interface{}, cols ...string) error {
return nil
}
// ReadForUpdate ...
func (f *FakeOrmer) ReadForUpdate(md interface{}, cols ...string) error {
return nil
}
// ReadOrCreate ...
func (f *FakeOrmer) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) {
return false, 0, nil
}
// Insert ...
func (f *FakeOrmer) Insert(interface{}) (int64, error) {
return 0, nil
}
// InsertOrUpdate ...
func (f *FakeOrmer) InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error) {
return 0, nil
}
// InsertMulti ...
func (f *FakeOrmer) InsertMulti(bulk int, mds interface{}) (int64, error) {
return 0, nil
}
// Update ...
func (f *FakeOrmer) Update(md interface{}, cols ...string) (int64, error) {
return 0, nil
}
// Delete ...
func (f *FakeOrmer) Delete(md interface{}, cols ...string) (int64, error) {
return 0, nil
}
// LoadRelated ...
func (f *FakeOrmer) LoadRelated(md interface{}, name string, args ...interface{}) (int64, error) {
return 0, nil
}
// QueryM2M ...
func (f *FakeOrmer) QueryM2M(md interface{}, name string) orm.QueryM2Mer {
return nil
}
// QueryTable ...
func (f *FakeOrmer) QueryTable(ptrStructOrTableName interface{}) orm.QuerySeter {
return nil
}
// Using ...
func (f *FakeOrmer) Using(name string) error {
return nil
}
// Begin ...
func (f *FakeOrmer) Begin() error {
return nil
}
// BeginTx ...
func (f *FakeOrmer) BeginTx(ctx context.Context, opts *sql.TxOptions) error {
return nil
}
// Commit ...
func (f *FakeOrmer) Commit() error {
return nil
}
// Rollback ...
func (f *FakeOrmer) Rollback() error {
return nil
}
// Raw ...
func (f *FakeOrmer) Raw(query string, args ...interface{}) orm.RawSeter {
return nil
}
// Driver ...
func (f *FakeOrmer) Driver() orm.Driver {
return nil
}
// DBStats ...
func (f *FakeOrmer) DBStats() *sql.DBStats {
return nil
}