From 9c6bb5a83508e76577d9dd3ff45942f2ae7be83a Mon Sep 17 00:00:00 2001 From: what Date: Thu, 20 Aug 2026 17:09:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20SelectDataset=20=E6=96=B0=E5=A2=9E=20Ex?= =?UTF-8?q?ists/ExistsContext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 生成 SELECT 1 FROM ... LIMIT 1 判断是否存在符合条件的行,不用调用方自己拼 COUNT(*) 或者查完整行再判断长度。 --- select_dataset.go | 11 +++++++++ select_dataset_test.go | 52 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/select_dataset.go b/select_dataset.go index b89de85..3384f8b 100644 --- a/select_dataset.go +++ b/select_dataset.go @@ -701,6 +701,17 @@ func (sd *SelectDataset) ScanValContext(ctx context.Context, i interface{}) (boo } // Generates the SELECT COUNT(*) sql for this dataset and uses Exec#ScanVal to scan the result into an int64. +// Generates SELECT 1 FROM ... LIMIT 1 and returns true if any row exists. +func (sd *SelectDataset) Exists() (bool, error) { + return sd.ExistsContext(context.Background()) +} + +// Generates SELECT 1 FROM ... LIMIT 1 and returns true if any row exists. +func (sd *SelectDataset) ExistsContext(ctx context.Context) (bool, error) { + var v int64 + return sd.Select(L("1")).Limit(1).ScanValContext(ctx, &v) +} + func (sd *SelectDataset) Count() (int64, error) { return sd.CountContext(context.Background()) } diff --git a/select_dataset_test.go b/select_dataset_test.go index 19c1b60..4adcd10 100644 --- a/select_dataset_test.go +++ b/select_dataset_test.go @@ -1618,6 +1618,58 @@ func (sds *selectDatasetSuite) TestSetError() { sds.Equal(err1, err) } +func (sds *selectDatasetSuite) TestExists() { + mDB, sqlMock, err := sqlmock.New() + sds.NoError(err) + sqlMock.ExpectQuery(`SELECT 1 FROM "items" LIMIT 1`). + WithArgs(). + WillReturnRows(sqlmock.NewRows([]string{"1"}).FromCSVString("1")) + + db := dbv2.New("mock", mDB) + exists, err := db.From("items").Exists() + sds.NoError(err) + sds.True(exists) +} + +func (sds *selectDatasetSuite) TestExists_NotFound() { + mDB, sqlMock, err := sqlmock.New() + sds.NoError(err) + sqlMock.ExpectQuery(`SELECT 1 FROM "items" LIMIT 1`). + WithArgs(). + WillReturnRows(sqlmock.NewRows([]string{"1"})) + + db := dbv2.New("mock", mDB) + exists, err := db.From("items").Exists() + sds.NoError(err) + sds.False(exists) +} + +func (sds *selectDatasetSuite) TestExists_WithWhere() { + mDB, sqlMock, err := sqlmock.New() + sds.NoError(err) + sqlMock.ExpectQuery(`SELECT 1 FROM "items" WHERE \("name" = 'Bob'\) LIMIT 1`). + WithArgs(). + WillReturnRows(sqlmock.NewRows([]string{"1"}).FromCSVString("1")) + + db := dbv2.New("mock", mDB) + exists, err := db.From("items").Where(dbv2.C("name").Eq("Bob")).Exists() + sds.NoError(err) + sds.True(exists) +} + +func (sds *selectDatasetSuite) TestExists_WithPreparedStatement() { + mDB, sqlMock, err := sqlmock.New() + sds.NoError(err) + sqlMock.ExpectQuery(`SELECT 1 FROM "items" WHERE \("name" = \?\) LIMIT \?`). + WithArgs("Bob", 1). + WillReturnRows(sqlmock.NewRows([]string{"1"}).FromCSVString("1")) + + db := dbv2.New("mock", mDB) + exists, err := db.From("items").Prepared(true).Where(dbv2.C("name").Eq("Bob")).Exists() + sds.NoError(err) + sds.True(exists) +} + func TestSelectDataset(t *testing.T) { suite.Run(t, new(selectDatasetSuite)) }