Преглед на файлове

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	readme-cn.md
SongZihuan преди 1 година
родител
ревизия
011d8b100a

+ 13 - 5
core/collection/ring.go

@@ -25,8 +25,14 @@ func (r *Ring) Add(v any) {
 	r.lock.Lock()
 	defer r.lock.Unlock()
 
-	r.elements[r.index%len(r.elements)] = v
+	rlen := len(r.elements)
+	r.elements[r.index%rlen] = v
 	r.index++
+
+	// prevent ring index overflow
+	if r.index >= rlen<<1 {
+		r.index -= rlen
+	}
 }
 
 // Take takes all items from r.
@@ -36,16 +42,18 @@ func (r *Ring) Take() []any {
 
 	var size int
 	var start int
-	if r.index > len(r.elements) {
-		size = len(r.elements)
-		start = r.index % len(r.elements)
+	rlen := len(r.elements)
+
+	if r.index > rlen {
+		size = rlen
+		start = r.index % rlen
 	} else {
 		size = r.index
 	}
 
 	elements := make([]any, size)
 	for i := 0; i < size; i++ {
-		elements[i] = r.elements[(start+i)%len(r.elements)]
+		elements[i] = r.elements[(start+i)%rlen]
 	}
 
 	return elements

+ 9 - 8
core/proc/signals.go

@@ -6,18 +6,20 @@ import (
 	"os"
 	"os/signal"
 	"syscall"
+	"time"
 
 	"github.com/zeromicro/go-zero/core/logx"
 )
 
-const timeFormat = "0102150405"
+const (
+	profileDuration = time.Minute
+	timeFormat      = "0102150405"
+)
 
 var done = make(chan struct{})
 
 func init() {
 	go func() {
-		var profiler Stopper
-
 		// https://golang.org/pkg/os/signal/#Notify
 		signals := make(chan os.Signal, 1)
 		signal.Notify(signals, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGTERM, syscall.SIGINT)
@@ -28,12 +30,11 @@ func init() {
 			case syscall.SIGUSR1:
 				dumpGoroutines(fileCreator{})
 			case syscall.SIGUSR2:
-				if profiler == nil {
-					profiler = StartProfile()
-				} else {
+				profiler := StartProfile()
+				go func() {
+					<-time.After(profileDuration)
 					profiler.Stop()
-					profiler = nil
-				}
+				}()
 			case syscall.SIGTERM:
 				stopOnSignal()
 				gracefulStop(signals, syscall.SIGTERM)

+ 0 - 0
internal/dbtest/sql.go → core/stores/dbtest/sql.go


+ 0 - 2
core/stores/mon/bulkinserter_test.go

@@ -11,8 +11,6 @@ import (
 
 func TestBulkInserter(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{{Key: "ok", Value: 1}}...))
 		bulk, err := NewBulkInserter(createModel(mt).Collection)

+ 0 - 2
core/stores/mon/clientmanager_test.go

@@ -9,8 +9,6 @@ import (
 
 func TestClientManger_getClient(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		Inject(mtest.ClusterURI(), mt.Client)
 		cli, err := getClient(mtest.ClusterURI())

+ 0 - 39
core/stores/mon/collection_test.go

@@ -68,7 +68,6 @@ func TestKeepPromise_keep(t *testing.T) {
 
 func TestNewCollection(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
 	mt.Run("test", func(mt *mtest.T) {
 		coll := mt.Coll
 		assert.NotNil(t, coll)
@@ -79,7 +78,6 @@ func TestNewCollection(t *testing.T) {
 
 func TestCollection_Aggregate(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
 	mt.Run("test", func(mt *mtest.T) {
 		coll := mt.Coll
 		assert.NotNil(t, coll)
@@ -96,8 +94,6 @@ func TestCollection_Aggregate(t *testing.T) {
 
 func TestCollection_BulkWrite(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -119,8 +115,6 @@ func TestCollection_BulkWrite(t *testing.T) {
 
 func TestCollection_CountDocuments(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -145,8 +139,6 @@ func TestCollection_CountDocuments(t *testing.T) {
 
 func TestDecoratedCollection_DeleteMany(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -165,8 +157,6 @@ func TestDecoratedCollection_DeleteMany(t *testing.T) {
 
 func TestCollection_Distinct(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -185,8 +175,6 @@ func TestCollection_Distinct(t *testing.T) {
 
 func TestCollection_EstimatedDocumentCount(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -205,8 +193,6 @@ func TestCollection_EstimatedDocumentCount(t *testing.T) {
 
 func TestCollection_Find(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -253,8 +239,6 @@ func TestCollection_Find(t *testing.T) {
 
 func TestCollection_FindOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -297,8 +281,6 @@ func TestCollection_FindOne(t *testing.T) {
 
 func TestCollection_FindOneAndDelete(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -328,8 +310,6 @@ func TestCollection_FindOneAndDelete(t *testing.T) {
 
 func TestCollection_FindOneAndReplace(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -360,8 +340,6 @@ func TestCollection_FindOneAndReplace(t *testing.T) {
 
 func TestCollection_FindOneAndUpdate(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -393,8 +371,6 @@ func TestCollection_FindOneAndUpdate(t *testing.T) {
 
 func TestCollection_InsertOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -413,8 +389,6 @@ func TestCollection_InsertOne(t *testing.T) {
 
 func TestCollection_InsertMany(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -437,8 +411,6 @@ func TestCollection_InsertMany(t *testing.T) {
 
 func TestCollection_DeleteOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -457,8 +429,6 @@ func TestCollection_DeleteOne(t *testing.T) {
 
 func TestCollection_DeleteMany(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -477,8 +447,6 @@ func TestCollection_DeleteMany(t *testing.T) {
 
 func TestCollection_ReplaceOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -500,8 +468,6 @@ func TestCollection_ReplaceOne(t *testing.T) {
 
 func TestCollection_UpdateOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -522,8 +488,6 @@ func TestCollection_UpdateOne(t *testing.T) {
 
 func TestCollection_UpdateByID(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -544,8 +508,6 @@ func TestCollection_UpdateByID(t *testing.T) {
 
 func TestCollection_UpdateMany(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		c := decoratedCollection{
 			Collection: mt.Coll,
@@ -566,7 +528,6 @@ func TestCollection_UpdateMany(t *testing.T) {
 
 func TestDecoratedCollection_LogDuration(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
 	c := decoratedCollection{
 		Collection: mt.Coll,
 		brk:        breaker.NewBreaker(),

+ 0 - 18
core/stores/mon/model_test.go

@@ -12,8 +12,6 @@ import (
 
 func TestModel_StartSession(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(mt)
 		sess, err := m.StartSession()
@@ -34,8 +32,6 @@ func TestModel_StartSession(t *testing.T) {
 
 func TestModel_Aggregate(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(mt)
 		find := mtest.CreateCursorResponse(
@@ -71,8 +67,6 @@ func TestModel_Aggregate(t *testing.T) {
 
 func TestModel_DeleteMany(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(mt)
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{{Key: "n", Value: 1}}...))
@@ -88,8 +82,6 @@ func TestModel_DeleteMany(t *testing.T) {
 
 func TestModel_DeleteOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(mt)
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{{Key: "n", Value: 1}}...))
@@ -105,8 +97,6 @@ func TestModel_DeleteOne(t *testing.T) {
 
 func TestModel_Find(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(mt)
 		find := mtest.CreateCursorResponse(
@@ -142,8 +132,6 @@ func TestModel_Find(t *testing.T) {
 
 func TestModel_FindOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(mt)
 		find := mtest.CreateCursorResponse(
@@ -170,8 +158,6 @@ func TestModel_FindOne(t *testing.T) {
 
 func TestModel_FindOneAndDelete(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(mt)
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
@@ -189,8 +175,6 @@ func TestModel_FindOneAndDelete(t *testing.T) {
 
 func TestModel_FindOneAndReplace(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(mt)
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
@@ -212,8 +196,6 @@ func TestModel_FindOneAndReplace(t *testing.T) {
 
 func TestModel_FindOneAndUpdate(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(mt)
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{

+ 0 - 48
core/stores/monc/cachedmodel_test.go

@@ -17,8 +17,6 @@ import (
 
 func TestNewModel(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		_, err := newModel("foo", mt.DB.Name(), mt.Coll.Name(), nil)
 		assert.NotNil(mt, err)
@@ -27,8 +25,6 @@ func TestNewModel(t *testing.T) {
 
 func TestModel_DelCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(t, mt)
 		assert.Nil(t, m.cache.Set("foo", "bar"))
@@ -42,8 +38,6 @@ func TestModel_DelCache(t *testing.T) {
 
 func TestModel_DeleteOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{{Key: "n", Value: 1}}...))
 		m := createModel(t, mt)
@@ -65,8 +59,6 @@ func TestModel_DeleteOne(t *testing.T) {
 
 func TestModel_DeleteOneNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{{Key: "n", Value: 1}}...))
 		m := createModel(t, mt)
@@ -81,8 +73,6 @@ func TestModel_DeleteOneNoCache(t *testing.T) {
 
 func TestModel_FindOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		resp := mtest.CreateCursorResponse(
 			1,
@@ -104,8 +94,6 @@ func TestModel_FindOne(t *testing.T) {
 
 func TestModel_FindOneNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		resp := mtest.CreateCursorResponse(
 			1,
@@ -126,8 +114,6 @@ func TestModel_FindOneNoCache(t *testing.T) {
 
 func TestModel_FindOneAndDelete(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -152,8 +138,6 @@ func TestModel_FindOneAndDelete(t *testing.T) {
 
 func TestModel_FindOneAndDeleteNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -169,8 +153,6 @@ func TestModel_FindOneAndDeleteNoCache(t *testing.T) {
 
 func TestModel_FindOneAndReplace(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -201,8 +183,6 @@ func TestModel_FindOneAndReplace(t *testing.T) {
 
 func TestModel_FindOneAndReplaceNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -220,8 +200,6 @@ func TestModel_FindOneAndReplaceNoCache(t *testing.T) {
 
 func TestModel_FindOneAndUpdate(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -252,8 +230,6 @@ func TestModel_FindOneAndUpdate(t *testing.T) {
 
 func TestModel_FindOneAndUpdateNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -271,8 +247,6 @@ func TestModel_FindOneAndUpdateNoCache(t *testing.T) {
 
 func TestModel_GetCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(t, mt)
 		assert.NotNil(t, m.cache)
@@ -285,8 +259,6 @@ func TestModel_GetCache(t *testing.T) {
 
 func TestModel_InsertOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -318,8 +290,6 @@ func TestModel_InsertOne(t *testing.T) {
 
 func TestModel_InsertOneNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -335,8 +305,6 @@ func TestModel_InsertOneNoCache(t *testing.T) {
 
 func TestModel_ReplaceOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -368,8 +336,6 @@ func TestModel_ReplaceOne(t *testing.T) {
 
 func TestModel_ReplaceOneNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -385,8 +351,6 @@ func TestModel_ReplaceOneNoCache(t *testing.T) {
 
 func TestModel_SetCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		m := createModel(t, mt)
 		assert.Nil(t, m.SetCache("foo", "bar"))
@@ -398,8 +362,6 @@ func TestModel_SetCache(t *testing.T) {
 
 func TestModel_UpdateByID(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -431,8 +393,6 @@ func TestModel_UpdateByID(t *testing.T) {
 
 func TestModel_UpdateByIDNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -448,8 +408,6 @@ func TestModel_UpdateByIDNoCache(t *testing.T) {
 
 func TestModel_UpdateMany(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -483,8 +441,6 @@ func TestModel_UpdateMany(t *testing.T) {
 
 func TestModel_UpdateManyNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -500,8 +456,6 @@ func TestModel_UpdateManyNoCache(t *testing.T) {
 
 func TestModel_UpdateOne(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},
@@ -533,8 +487,6 @@ func TestModel_UpdateOne(t *testing.T) {
 
 func TestModel_UpdateOneNoCache(t *testing.T) {
 	mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
-	defer mt.Close()
-
 	mt.Run("test", func(mt *mtest.T) {
 		mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{
 			{Key: "value", Value: bson.D{{Key: "foo", Value: "bar"}}},

+ 1 - 1
core/stores/sqlc/cachedsql_test.go

@@ -22,11 +22,11 @@ import (
 	"github.com/zeromicro/go-zero/core/logx"
 	"github.com/zeromicro/go-zero/core/stat"
 	"github.com/zeromicro/go-zero/core/stores/cache"
+	"github.com/zeromicro/go-zero/core/stores/dbtest"
 	"github.com/zeromicro/go-zero/core/stores/redis"
 	"github.com/zeromicro/go-zero/core/stores/redis/redistest"
 	"github.com/zeromicro/go-zero/core/stores/sqlx"
 	"github.com/zeromicro/go-zero/core/syncx"
-	"github.com/zeromicro/go-zero/internal/dbtest"
 )
 
 func init() {

+ 1 - 1
core/stores/sqlx/bulkinserter_test.go

@@ -12,7 +12,7 @@ import (
 
 	"github.com/DATA-DOG/go-sqlmock"
 	"github.com/stretchr/testify/assert"
-	"github.com/zeromicro/go-zero/internal/dbtest"
+	"github.com/zeromicro/go-zero/core/stores/dbtest"
 )
 
 type mockedConn struct {

+ 1 - 1
core/stores/sqlx/orm_test.go

@@ -8,7 +8,7 @@ import (
 
 	"github.com/DATA-DOG/go-sqlmock"
 	"github.com/stretchr/testify/assert"
-	"github.com/zeromicro/go-zero/internal/dbtest"
+	"github.com/zeromicro/go-zero/core/stores/dbtest"
 )
 
 func TestUnmarshalRowBool(t *testing.T) {

+ 1 - 1
core/stores/sqlx/sqlconn_test.go

@@ -10,8 +10,8 @@ import (
 	"github.com/stretchr/testify/assert"
 	"github.com/zeromicro/go-zero/core/breaker"
 	"github.com/zeromicro/go-zero/core/logx"
+	"github.com/zeromicro/go-zero/core/stores/dbtest"
 	"github.com/zeromicro/go-zero/core/trace/tracetest"
-	"github.com/zeromicro/go-zero/internal/dbtest"
 )
 
 const mockedDatasource = "sqlmock"

+ 1 - 1
core/stores/sqlx/tx_test.go

@@ -9,7 +9,7 @@ import (
 	"github.com/DATA-DOG/go-sqlmock"
 	"github.com/stretchr/testify/assert"
 	"github.com/zeromicro/go-zero/core/breaker"
-	"github.com/zeromicro/go-zero/internal/dbtest"
+	"github.com/zeromicro/go-zero/core/stores/dbtest"
 )
 
 const (

+ 13 - 13
go.mod

@@ -13,16 +13,16 @@ require (
 	github.com/golang/mock v1.6.0
 	github.com/golang/protobuf v1.5.3
 	github.com/google/uuid v1.4.0
-	github.com/jackc/pgx/v5 v5.5.0
+	github.com/jackc/pgx/v5 v5.5.1
 	github.com/jhump/protoreflect v1.15.3
 	github.com/olekukonko/tablewriter v0.0.5
 	github.com/pelletier/go-toml/v2 v2.1.0
 	github.com/prometheus/client_golang v1.17.0
 	github.com/spaolacci/murmur3 v1.1.0
 	github.com/stretchr/testify v1.8.4
-	go.etcd.io/etcd/api/v3 v3.5.10
-	go.etcd.io/etcd/client/v3 v3.5.10
-	go.mongodb.org/mongo-driver v1.12.1
+	go.etcd.io/etcd/api/v3 v3.5.11
+	go.etcd.io/etcd/client/v3 v3.5.11
+	go.mongodb.org/mongo-driver v1.13.1
 	go.opentelemetry.io/otel v1.19.0
 	go.opentelemetry.io/otel/exporters/jaeger v1.17.0
 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0
@@ -33,18 +33,18 @@ require (
 	go.opentelemetry.io/otel/trace v1.19.0
 	go.uber.org/automaxprocs v1.5.3
 	go.uber.org/goleak v1.2.1
-	golang.org/x/net v0.18.0
-	golang.org/x/sys v0.14.0
-	golang.org/x/time v0.4.0
+	golang.org/x/net v0.19.0
+	golang.org/x/sys v0.15.0
+	golang.org/x/time v0.5.0
 	google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b
 	google.golang.org/grpc v1.59.0
 	google.golang.org/protobuf v1.31.0
 	gopkg.in/cheggaaa/pb.v1 v1.0.28
 	gopkg.in/h2non/gock.v1 v1.1.2
 	gopkg.in/yaml.v2 v2.4.0
-	k8s.io/api v0.28.3
-	k8s.io/apimachinery v0.28.3
-	k8s.io/client-go v0.28.3
+	k8s.io/api v0.28.4
+	k8s.io/apimachinery v0.28.4
+	k8s.io/client-go v0.28.4
 	k8s.io/utils v0.0.0-20230726121419-3b25d923346b
 )
 
@@ -97,17 +97,17 @@ require (
 	github.com/xdg-go/stringprep v1.0.4 // indirect
 	github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
 	github.com/yuin/gopher-lua v1.1.0 // indirect
-	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
+	go.etcd.io/etcd/client/pkg/v3 v3.5.11 // indirect
 	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect
 	go.opentelemetry.io/otel/metric v1.19.0 // indirect
 	go.opentelemetry.io/proto/otlp v1.0.0 // indirect
 	go.uber.org/atomic v1.10.0 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
 	go.uber.org/zap v1.24.0 // indirect
-	golang.org/x/crypto v0.15.0 // indirect
+	golang.org/x/crypto v0.16.0 // indirect
 	golang.org/x/oauth2 v0.12.0 // indirect
 	golang.org/x/sync v0.3.0 // indirect
-	golang.org/x/term v0.14.0 // indirect
+	golang.org/x/term v0.15.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	google.golang.org/appengine v1.6.8 // indirect
 	google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect

+ 26 - 26
go.sum

@@ -90,8 +90,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
 github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
 github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
 github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
-github.com/jackc/pgx/v5 v5.5.0 h1:NxstgwndsTRy7eq9/kqYc/BZh5w2hHJV86wjvO+1xPw=
-github.com/jackc/pgx/v5 v5.5.0/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
+github.com/jackc/pgx/v5 v5.5.1 h1:5I9etrGkLrN+2XPCsi6XLlV5DITbSL/xBZdmAxFcXPI=
+github.com/jackc/pgx/v5 v5.5.1/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
 github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
 github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
 github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls=
@@ -188,14 +188,14 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE=
 github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
-go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k=
-go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI=
-go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0=
-go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U=
-go.etcd.io/etcd/client/v3 v3.5.10 h1:W9TXNZ+oB3MCd/8UjxHTWK5J9Nquw9fQBLJd5ne5/Ao=
-go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc=
-go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE=
-go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ=
+go.etcd.io/etcd/api/v3 v3.5.11 h1:B54KwXbWDHyD3XYAwprxNzTe7vlhR69LuBgZnMVvS7E=
+go.etcd.io/etcd/api/v3 v3.5.11/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4=
+go.etcd.io/etcd/client/pkg/v3 v3.5.11 h1:bT2xVspdiCj2910T0V+/KHcVKjkUrCZVtk8J2JF2z1A=
+go.etcd.io/etcd/client/pkg/v3 v3.5.11/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
+go.etcd.io/etcd/client/v3 v3.5.11 h1:ajWtgoNSZJ1gmS8k+icvPtqsqEav+iUorF7b0qozgUU=
+go.etcd.io/etcd/client/v3 v3.5.11/go.mod h1:a6xQUEqFJ8vztO1agJh/KQKOMfFI8og52ZconzcDJwE=
+go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
+go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
 go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
 go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
 go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
@@ -234,8 +234,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
-golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
+golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
+golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -248,8 +248,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
-golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
+golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
 golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
 golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -273,12 +273,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
-golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
-golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
+golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
+golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -287,8 +287,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
-golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@@ -330,12 +330,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM=
-k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc=
-k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A=
-k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8=
-k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4=
-k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo=
+k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY=
+k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0=
+k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8=
+k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg=
+k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY=
+k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4=
 k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
 k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
 k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=

+ 2 - 2
tools/goctl/api/dartgen/genapi.go

@@ -15,8 +15,8 @@ import '../data/{{with .Info}}{{getBaseName .Title}}{{end}}.dart';
 {{range .Routes}}
 /// --{{.Path}}--
 ///
-/// 请求: {{with .RequestType}}{{.Name}}{{end}}
-/// 返回: {{with .ResponseType}}{{.Name}}{{end}}
+/// request: {{with .RequestType}}{{.Name}}{{end}}
+/// response: {{with .ResponseType}}{{.Name}}{{end}}
 Future {{pathToFuncName .Path}}( {{if ne .Method "get"}}{{with .RequestType}}{{.Name}} request,{{end}}{{end}}
     {Function({{with .ResponseType}}{{.Name}}{{end}}) ok,
     Function(String) fail,

+ 4 - 0
tools/goctl/api/dartgen/gendata.go

@@ -51,6 +51,8 @@ class {{.Name}} {
 						m['{{getPropertyFromMember .}}']?.cast<{{getCoreType .Type.Name}}>() {{appendDefaultEmptyValue .Type.Name}}
 					{{else if isClassListType .Type.Name}}
 						((m['{{getPropertyFromMember .}}'] {{appendDefaultEmptyValue .Type.Name}}) as List<dynamic>).map((i) => {{getCoreType .Type.Name}}.fromJson(i)).toList()
+					{{else if isMapType .Type.Name}}
+						{{if isNumberType .Type.Name}}num{{else}}{{.Type.Name}}{{end}}.from(m['{{getPropertyFromMember .}}'] ?? {})
 					{{else}}
 						{{.Type.Name}}.fromJson(m['{{getPropertyFromMember .}}']){{end}}
 			,{{end}}
@@ -61,6 +63,8 @@ class {{.Name}} {
 			'{{getPropertyFromMember .}}': 
 				{{if isDirectType .Type.Name}}
 					{{lowCamelCase .Name}}
+				{{else if isMapType .Type.Name}}
+					{{lowCamelCase .Name}}
 				{{else if isClassListType .Type.Name}}
 					{{lowCamelCase .Name}}{{if isNullableType .Type.Name}}?{{end}}.map((i) => i{{if isListItemsNullable .Type.Name}}?{{end}}.toJson())
 				{{else}}

+ 27 - 22
tools/goctl/api/dartgen/vars.go

@@ -3,23 +3,24 @@ package dartgen
 import "text/template"
 
 var funcMap = template.FuncMap{
+	"appendNullCoalescing":            appendNullCoalescing,
+	"appendDefaultEmptyValue":         appendDefaultEmptyValue,
+	"extractPositionalParamsFromPath": extractPositionalParamsFromPath,
 	"getBaseName":                     getBaseName,
+	"getCoreType":                     getCoreType,
 	"getPropertyFromMember":           getPropertyFromMember,
-	"isDirectType":                    isDirectType,
+	"hasUrlPathParams":                hasUrlPathParams,
+	"isAtomicListType":                isAtomicListType,
 	"isAtomicType":                    isAtomicType,
-	"isNumberType":                    isNumberType,
+	"isDirectType":                    isDirectType,
 	"isClassListType":                 isClassListType,
-	"isAtomicListType":                isAtomicListType,
 	"isListItemsNullable":             isListItemsNullable,
+	"isMapType":                       isMapType,
 	"isNullableType":                  isNullableType,
-	"appendNullCoalescing":            appendNullCoalescing,
-	"appendDefaultEmptyValue":         appendDefaultEmptyValue,
-	"getCoreType":                     getCoreType,
+	"isNumberType":                    isNumberType,
 	"lowCamelCase":                    lowCamelCase,
-	"normalizeHandlerName":            normalizeHandlerName,
-	"hasUrlPathParams":                hasUrlPathParams,
-	"extractPositionalParamsFromPath": extractPositionalParamsFromPath,
 	"makeDartRequestUrlPath":          makeDartRequestUrlPath,
+	"normalizeHandlerName":            normalizeHandlerName,
 }
 
 const (
@@ -28,28 +29,32 @@ import 'dart:convert';
 import '../vars/kv.dart';
 import '../vars/vars.dart';
 
-/// 发送POST请求.
+/// Send GET request.
 ///
-/// data:为你要post的结构体,我们会帮你转换成json字符串;
-/// ok函数:请求成功的时候调用,fail函数:请求失败的时候会调用,eventually函数:无论成功失败都会调用
-Future apiPost(String path, dynamic data,
+/// ok: the function that will be called on success.
+/// fail:the fuction that will be called on failure.
+/// eventually:the function that will be called regardless of success or failure.
+Future apiGet(String path,
     {Map<String, String> header,
     Function(Map<String, dynamic>) ok,
     Function(String) fail,
     Function eventually}) async {
-  await _apiRequest('POST', path, data,
+  await _apiRequest('GET', path, null,
       header: header, ok: ok, fail: fail, eventually: eventually);
 }
 
-/// 发送GET请求.
+/// Send POST request.
 ///
-/// ok函数:请求成功的时候调用,fail函数:请求失败的时候会调用,eventually函数:无论成功失败都会调用
-Future apiGet(String path,
+/// data: the data to post, it will be marshaled to json automatically.
+/// ok: the function that will be called on success.
+/// fail:the fuction that will be called on failure.
+/// eventually:the function that will be called regardless of success or failure.
+Future apiPost(String path, dynamic data,
     {Map<String, String> header,
     Function(Map<String, dynamic>) ok,
     Function(String) fail,
     Function eventually}) async {
-  await _apiRequest('GET', path, null,
+  await _apiRequest('POST', path, data,
       header: header, ok: ok, fail: fail, eventually: eventually);
 }
 
@@ -212,11 +217,11 @@ Future _apiRequest(String method, String path, dynamic data,
 	}`
 
 	tokensFileContent = `class Tokens {
-  /// 用于访问的token, 每次请求都必须带在Header里面
+  /// the token used to access, it must be carried in the header of each request
   final String accessToken;
   final int accessExpire;
 
-  /// 用于刷新token
+  /// the token used to refresh
   final String refreshToken;
   final int refreshExpire;
   final int refreshAfter;
@@ -247,11 +252,11 @@ Future _apiRequest(String method, String path, dynamic data,
 `
 
 	tokensFileContentV2 = `class Tokens {
-  /// 用于访问的token, 每次请求都必须带在Header里面
+  /// the token used to access, it must be carried in the header of each request
   final String accessToken;
   final int accessExpire;
 
-  /// 用于刷新token
+  /// the token used to refresh
   final String refreshToken;
   final int refreshExpire;
   final int refreshAfter;

+ 1 - 1
tools/goctl/model/cmd.go

@@ -46,7 +46,7 @@ func init() {
 	datasourceCmdFlags.StringVar(&command.VarStringBranch, "branch")
 
 	pgDatasourceCmdFlags.StringVar(&command.VarStringURL, "url")
-	pgDatasourceCmdFlags.StringVarP(&command.VarStringTable, "table", "t")
+	pgDatasourceCmdFlags.StringSliceVarP(&command.VarStringSliceTable, "table", "t")
 	pgDatasourceCmdFlags.StringVarPWithDefaultValue(&command.VarStringSchema, "schema", "s", "public")
 	pgDatasourceCmdFlags.BoolVarP(&command.VarBoolCache, "cache", "c")
 	pgDatasourceCmdFlags.StringVarP(&command.VarStringDir, "dir", "d")

+ 3 - 2
tools/goctl/model/sql/README.MD

@@ -344,7 +344,7 @@ OPTIONS:
   
   理论上是没任何问题,但是我们认为,对于model层的数据操作均是以整个结构体为单位,包括查询,我不建议只查询某部分字段(不反对),否则我们的缓存就没有意义了。
 
-* 为什么不支持`findPageLimit`、`findAll`这么模式代码生层
+* 为什么不支持`findPageLimit`、`findAll`这种模型代码生成
   
   目前,我认为除了基本的CURD外,其他的代码均属于<i>业务型</i>代码,这个我觉得开发人员根据业务需要进行编写更好。
 
@@ -378,4 +378,5 @@ OPTIONS:
 | longtext       | string          | sql.NullString                         |
 | enum           | string          | sql.NullString                         |
 | set            | string          | sql.NullString                         |
-| json           | string          | sql.NullString                         |
+| json           | string          | sql.NullString                         |
+

+ 4 - 11
tools/goctl/model/sql/command/command.go

@@ -35,8 +35,6 @@ var (
 	VarStringURL string
 	// VarStringSliceTable describes tables.
 	VarStringSliceTable []string
-	// VarStringTable describes a table of sql.
-	VarStringTable string
 	// VarStringStyle describes the style.
 	VarStringStyle string
 	// VarStringDatabase describes the database.
@@ -211,14 +209,14 @@ func PostgreSqlDataSource(_ *cobra.Command, _ []string) error {
 		schema = "public"
 	}
 
-	pattern := strings.TrimSpace(VarStringTable)
+	patterns := parseTableList(VarStringSliceTable)
 	cfg, err := config.NewConfig(style)
 	if err != nil {
 		return err
 	}
 	ignoreColumns := mergeColumns(VarStringSliceIgnoreColumns)
 
-	return fromPostgreSqlDataSource(url, pattern, dir, schema, cfg, cache, idea, VarBoolStrict, ignoreColumns)
+	return fromPostgreSqlDataSource(url, patterns, dir, schema, cfg, cache, idea, VarBoolStrict, ignoreColumns)
 }
 
 type ddlArg struct {
@@ -330,7 +328,7 @@ func fromMysqlDataSource(arg dataSourceArg) error {
 	return generator.StartFromInformationSchema(matchTables, arg.cache, arg.strict)
 }
 
-func fromPostgreSqlDataSource(url, pattern, dir, schema string, cfg *config.Config, cache, idea, strict bool, ignoreColumns []string) error {
+func fromPostgreSqlDataSource(url string, pattern pattern, dir, schema string, cfg *config.Config, cache, idea, strict bool, ignoreColumns []string) error {
 	log := console.NewConsole(idea)
 	if len(url) == 0 {
 		log.Error("%v", "expected data source of postgresql, but nothing found")
@@ -351,12 +349,7 @@ func fromPostgreSqlDataSource(url, pattern, dir, schema string, cfg *config.Conf
 
 	matchTables := make(map[string]*model.Table)
 	for _, item := range tables {
-		match, err := filepath.Match(pattern, item)
-		if err != nil {
-			return err
-		}
-
-		if !match {
+		if !pattern.Match(item) {
 			continue
 		}
 

+ 10 - 13
tools/goctl/model/sql/parser/parser.go

@@ -8,7 +8,6 @@ import (
 
 	"github.com/zeromicro/ddl-parser/parser"
 	"github.com/zeromicro/go-zero/core/collection"
-
 	"github.com/zeromicro/go-zero/tools/goctl/model/sql/converter"
 	"github.com/zeromicro/go-zero/tools/goctl/model/sql/model"
 	"github.com/zeromicro/go-zero/tools/goctl/model/sql/util"
@@ -83,8 +82,9 @@ func Parse(filename, database string, strict bool) ([]*Table, error) {
 			primaryColumn    string
 			primaryColumnSet = collection.NewSet()
 			uniqueKeyMap     = make(map[string][]string)
-			normalKeyMap     = make(map[string][]string)
-			columns          = e.Columns
+			// Unused local variable
+			// normalKeyMap     = make(map[string][]string)
+			columns = e.Columns
 		)
 
 		for _, column := range columns {
@@ -127,6 +127,8 @@ func Parse(filename, database string, strict bool) ([]*Table, error) {
 			return nil, fmt.Errorf("%s: unexpected join primary key", prefix)
 		}
 
+		delete(uniqueKeyMap, indexNameGen(primaryColumn, "idx"))
+		delete(uniqueKeyMap, indexNameGen(primaryColumn, "unique"))
 		primaryKey, fieldM, err := convertColumns(columns, primaryColumn, strict)
 		if err != nil {
 			return nil, err
@@ -142,23 +144,18 @@ func Parse(filename, database string, strict bool) ([]*Table, error) {
 			}
 		}
 
-		var (
-			uniqueIndex = make(map[string][]*Field)
-			normalIndex = make(map[string][]*Field)
-		)
+		uniqueIndex := make(map[string][]*Field)
 
 		for indexName, each := range uniqueKeyMap {
 			for _, columnName := range each {
+				// Prevent a crash if there is a unique key constraint with a nil field.
+				if fieldM[columnName] == nil {
+					return nil, fmt.Errorf("table %s: unique key with error column name[%s]", e.Name, columnName)
+				}
 				uniqueIndex[indexName] = append(uniqueIndex[indexName], fieldM[columnName])
 			}
 		}
 
-		for indexName, each := range normalKeyMap {
-			for _, columnName := range each {
-				normalIndex[indexName] = append(normalIndex[indexName], fieldM[columnName])
-			}
-		}
-
 		checkDuplicateUniqueIndex(uniqueIndex, e.Name)
 
 		list = append(list, &Table{

+ 1 - 1
tools/goctl/model/sql/template/tpl/find-one.tpl

@@ -18,7 +18,7 @@ func (m *default{{.upperStartCamelObject}}Model) FindOne(ctx context.Context, {{
 	switch err {
 	case nil:
 		return &resp, nil
-	case sqlc.ErrNotFound:
+	case sqlx.ErrNotFound:
 		return nil, ErrNotFound
 	default:
 		return nil, err

+ 31 - 0
tools/goctl/pkg/parser/api/importstack/importstack.go

@@ -0,0 +1,31 @@
+package importstack
+
+import "errors"
+
+// ErrImportCycleNotAllowed defines an error for circular importing
+var ErrImportCycleNotAllowed = errors.New("import cycle not allowed")
+
+// ImportStack a stack of import paths
+type ImportStack []string
+
+func New() *ImportStack {
+	return &ImportStack{}
+}
+
+func (s *ImportStack) Push(p string) error {
+	for _, x := range *s {
+		if x == p {
+			return ErrImportCycleNotAllowed
+		}
+	}
+	*s = append(*s, p)
+	return nil
+}
+
+func (s *ImportStack) Pop() {
+	*s = (*s)[0 : len(*s)-1]
+}
+
+func (s *ImportStack) List() []string {
+	return *s
+}

+ 10 - 3
tools/goctl/pkg/parser/api/parser/analyzer.go

@@ -5,8 +5,10 @@ import (
 	"sort"
 	"strings"
 
+	"github.com/zeromicro/go-zero/core/lang"
 	"github.com/zeromicro/go-zero/tools/goctl/api/spec"
 	"github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/ast"
+	"github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/importstack"
 	"github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/placeholder"
 	"github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/token"
 )
@@ -390,9 +392,14 @@ func Parse(filename string, src interface{}) (*spec.ApiSpec, error) {
 		return nil, err
 	}
 
-	var importManager = make(map[string]placeholder.Type)
-	importManager[ast.Filename] = placeholder.PlaceHolder
-	api, err := convert2API(ast, importManager)
+	is := importstack.New()
+	err := is.Push(ast.Filename)
+	if err != nil {
+		return nil, err
+	}
+
+	importSet := map[string]lang.PlaceholderType{}
+	api, err := convert2API(ast, importSet, is)
 	if err != nil {
 		return nil, err
 	}

+ 19 - 13
tools/goctl/pkg/parser/api/parser/api.go

@@ -5,7 +5,9 @@ import (
 	"path/filepath"
 	"strings"
 
+	"github.com/zeromicro/go-zero/core/lang"
 	"github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/ast"
+	"github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/importstack"
 	"github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/placeholder"
 	"github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/token"
 )
@@ -18,15 +20,17 @@ type API struct {
 	importStmt    []ast.ImportStmt // ImportStmt block does not participate in code generation.
 	TypeStmt      []ast.TypeStmt
 	ServiceStmts  []*ast.ServiceStmt
-	importManager map[string]placeholder.Type
+	importManager *importstack.ImportStack
+	importSet     map[string]lang.PlaceholderType
 }
 
-func convert2API(a *ast.AST, importManager map[string]placeholder.Type) (*API, error) {
+func convert2API(a *ast.AST, importSet map[string]lang.PlaceholderType, is *importstack.ImportStack) (*API, error) {
 	var api = new(API)
-	api.importManager = make(map[string]placeholder.Type)
+	api.importManager = is
+	api.importSet = make(map[string]lang.PlaceholderType)
 	api.Filename = a.Filename
-	for k, v := range importManager {
-		api.importManager[k] = v
+	for k, v := range importSet {
+		api.importSet[k] = v
 	}
 	one := a.Stmts[0]
 	syntax, ok := one.(*ast.SyntaxStmt)
@@ -230,9 +234,6 @@ func (api *API) getAtServerValue(atServer *ast.AtServerStmt, key string) string
 }
 
 func (api *API) mergeAPI(in *API) error {
-	for k, v := range in.importManager {
-		api.importManager[k] = v
-	}
 	if api.Syntax.Value.Format() != in.Syntax.Value.Format() {
 		return ast.SyntaxError(in.Syntax.Value.Pos(),
 			"multiple syntax value expression, expected <%s>, got <%s>",
@@ -269,11 +270,15 @@ func (api *API) parseImportedAPI(imports []ast.ImportStmt) ([]*API, error) {
 			impPath = filepath.Join(dir, impPath)
 		}
 		// import cycle check
-		if _, ok := api.importManager[impPath]; ok {
-			return nil, ast.SyntaxError(tok.Position, "import circle not allowed")
-		} else {
-			api.importManager[impPath] = placeholder.PlaceHolder
+		if err := api.importManager.Push(impPath); err != nil {
+			return nil, ast.SyntaxError(tok.Position, err.Error())
+		}
+
+		if _, ok := api.importSet[impPath]; ok {
+			api.importManager.Pop()
+			continue
 		}
+		api.importSet[impPath] = lang.Placeholder
 
 		p := New(impPath, "")
 		ast := p.Parse()
@@ -281,7 +286,7 @@ func (api *API) parseImportedAPI(imports []ast.ImportStmt) ([]*API, error) {
 			return nil, err
 		}
 
-		nestedApi, err := convert2API(ast, api.importManager)
+		nestedApi, err := convert2API(ast, api.importSet, api.importManager)
 		if err != nil {
 			return nil, err
 		}
@@ -290,6 +295,7 @@ func (api *API) parseImportedAPI(imports []ast.ImportStmt) ([]*API, error) {
 			return nil, err
 		}
 
+		api.importManager.Pop()
 		list = append(list, nestedApi)
 
 		if err != nil {

+ 12 - 8
tools/goctl/pkg/parser/api/scanner/scanner.go

@@ -26,7 +26,6 @@ const (
 	stringOpen
 	stringClose
 	// string mode end
-
 )
 
 var missingInput = errors.New("missing input")
@@ -268,6 +267,7 @@ func (s *Scanner) scanNanosecond(bgPos int) token.Token {
 		return s.illegalToken()
 	}
 	s.readRune()
+
 	return token.Token{
 		Type:     token.DURATION,
 		Text:     string(s.data[bgPos:s.position]),
@@ -485,6 +485,7 @@ func (s *Scanner) scanLineComment() token.Token {
 	for s.ch != '\n' && s.ch != 0 {
 		s.readRune()
 	}
+
 	return token.Token{
 		Type:     token.COMMENT,
 		Text:     string(s.data[position:s.position]),
@@ -546,6 +547,7 @@ func (s *Scanner) assertExpected(actual token.Type, expected ...token.Type) erro
 		strings.Join(expects, " | "),
 		actual.String(),
 	))
+
 	return errors.New(text)
 }
 
@@ -560,6 +562,7 @@ func (s *Scanner) assertExpectedString(actual string, expected ...string) error
 		strings.Join(expects, " | "),
 		actual,
 	))
+
 	return errors.New(text)
 }
 
@@ -647,21 +650,22 @@ func NewScanner(filename string, src interface{}) (*Scanner, error) {
 }
 
 func readData(filename string, src interface{}) ([]byte, error) {
-	data, err := os.ReadFile(filename)
-	if err == nil {
+	if strings.HasSuffix(filename, ".api") {
+		data, err := os.ReadFile(filename)
+		if err != nil {
+			return nil, err
+		}
 		return data, nil
 	}
 
 	switch v := src.(type) {
 	case []byte:
-		data = append(data, v...)
+		return v, nil
 	case *bytes.Buffer:
-		data = v.Bytes()
+		return v.Bytes(), nil
 	case string:
-		data = []byte(v)
+		return []byte(v), nil
 	default:
 		return nil, fmt.Errorf("unsupported type: %T", src)
 	}
-
-	return data, nil
 }