Skip to content

Commit 13d3ff7

Browse files
sid200727claude
andcommitted
fix(storage): restore WalletStore squirrel migration after rebase
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Siddhi Khandelwal <siddhi.200727@gmail.com>
1 parent 6eff4f5 commit 13d3ff7

2 files changed

Lines changed: 75 additions & 58 deletions

File tree

token/services/storage/db/sql/common/wallet.go

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ import (
1212
"fmt"
1313
"time"
1414

15+
sq "github.com/Masterminds/squirrel"
1516
"github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
1617
"github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/collections/iterators"
1718
common2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/storage/driver/common"
1819
"github.com/hyperledger-labs/fabric-smart-client/platform/view/services/storage/driver/sql/common"
19-
q "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/storage/driver/sql/query"
20-
common3 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/storage/driver/sql/query/common"
21-
"github.com/hyperledger-labs/fabric-smart-client/platform/view/services/storage/driver/sql/query/cond"
2220
"github.com/hyperledger-labs/fabric-token-sdk/token"
2321
"github.com/hyperledger-labs/fabric-token-sdk/token/services/logging"
2422
"github.com/hyperledger-labs/fabric-token-sdk/token/services/storage/db/driver"
@@ -32,20 +30,20 @@ type WalletStore struct {
3230
readDB *sql.DB
3331
writeDB *sql.DB
3432
table walletTables
35-
ci common3.CondInterpreter
33+
pf sq.PlaceholderFormat
3634
}
3735

38-
func newWalletStore(readDB, writeDB *sql.DB, tables walletTables, ci common3.CondInterpreter) *WalletStore {
36+
func newWalletStore(readDB, writeDB *sql.DB, tables walletTables, pf sq.PlaceholderFormat) *WalletStore {
3937
return &WalletStore{
4038
readDB: readDB,
4139
writeDB: writeDB,
4240
table: tables,
43-
ci: ci,
41+
pf: pf,
4442
}
4543
}
4644

47-
func NewWalletStore(readDB, writeDB *sql.DB, tables TableNames, ci common3.CondInterpreter) (*WalletStore, error) {
48-
return newWalletStore(readDB, writeDB, walletTables{Wallets: tables.Wallets}, ci), nil
45+
func NewWalletStore(readDB, writeDB *sql.DB, tables TableNames, pf sq.PlaceholderFormat) (*WalletStore, error) {
46+
return newWalletStore(readDB, writeDB, walletTables{Wallets: tables.Wallets}, pf), nil
4947
}
5048

5149
func (db *WalletStore) CreateSchema() error {
@@ -54,11 +52,13 @@ func (db *WalletStore) CreateSchema() error {
5452

5553
func (db *WalletStore) GetWalletID(ctx context.Context, identity token.Identity, roleID int) (driver.WalletID, error) {
5654
idHash := identity.UniqueID()
57-
query, args := q.Select().
58-
FieldsByName("wallet_id").
59-
From(q.Table(db.table.Wallets)).
60-
Where(cond.And(cond.Eq("identity_hash", idHash), cond.Eq("role_id", roleID))).
61-
Format(db.ci)
55+
query, args, err := sq.Select("wallet_id").
56+
From(db.table.Wallets).
57+
Where(sq.And{sq.Eq{"identity_hash": idHash}, sq.Eq{"role_id": roleID}}).
58+
PlaceholderFormat(db.pf).ToSql()
59+
if err != nil {
60+
return "", errors.Wrapf(err, "failed building query for wallet id [%v]", idHash)
61+
}
6262

6363
result, err := common.QueryUnique[driver.WalletID](db.readDB, query, args...)
6464
if err != nil {
@@ -70,11 +70,13 @@ func (db *WalletStore) GetWalletID(ctx context.Context, identity token.Identity,
7070
}
7171

7272
func (db *WalletStore) GetWalletIDs(ctx context.Context, roleID int) ([]driver.WalletID, error) {
73-
query, args := q.SelectDistinct().
74-
FieldsByName("wallet_id").
75-
From(q.Table(db.table.Wallets)).
76-
Where(cond.Eq("role_id", roleID)).
77-
Format(db.ci)
73+
query, args, err := sq.Select("DISTINCT wallet_id").
74+
From(db.table.Wallets).
75+
Where(sq.Eq{"role_id": roleID}).
76+
PlaceholderFormat(db.pf).ToSql()
77+
if err != nil {
78+
return nil, errors.Wrapf(err, "failed building query for wallet ids")
79+
}
7880
logging.Debug(logger, query)
7981
rows, err := db.readDB.QueryContext(ctx, query, args...)
8082
if err != nil {
@@ -87,14 +89,17 @@ func (db *WalletStore) GetWalletIDs(ctx context.Context, roleID int) ([]driver.W
8789
}
8890

8991
func (db *WalletStore) StoreIdentity(ctx context.Context, identity token.Identity, eID string, wID driver.WalletID, roleID int, meta []byte) error {
90-
query, args := q.InsertInto(db.table.Wallets).
91-
Fields("identity_hash", "meta", "wallet_id", "role_id", "created_at", "enrollment_id").
92-
Row(identity.UniqueID(), meta, wID, roleID, time.Now().UTC(), eID).
93-
OnConflictDoNothing().
94-
Format()
92+
query, args, err := sq.Insert(db.table.Wallets).
93+
Columns("identity_hash", "meta", "wallet_id", "role_id", "created_at", "enrollment_id").
94+
Values(identity.UniqueID(), meta, wID, roleID, time.Now().UTC(), eID).
95+
Suffix("ON CONFLICT DO NOTHING").
96+
PlaceholderFormat(db.pf).ToSql()
97+
if err != nil {
98+
return errors.Wrapf(err, "failed building query for storing wallet [%v]", wID)
99+
}
95100
logging.Debug(logger, query)
96101

97-
_, err := db.writeDB.ExecContext(ctx, query, args...)
102+
_, err = db.writeDB.ExecContext(ctx, query, args...)
98103
if err != nil {
99104
return errors.Wrapf(err, "failed storing wallet [%v] for identity [%s]", wID, identity)
100105
}
@@ -105,11 +110,13 @@ func (db *WalletStore) StoreIdentity(ctx context.Context, identity token.Identit
105110

106111
func (db *WalletStore) LoadMeta(ctx context.Context, identity token.Identity, wID driver.WalletID, roleID int) ([]byte, error) {
107112
idHash := identity.UniqueID()
108-
query, args := q.Select().
109-
FieldsByName("meta").
110-
From(q.Table(db.table.Wallets)).
111-
Where(cond.And(cond.Eq("identity_hash", idHash), cond.Eq("wallet_id", wID), cond.Eq("role_id", roleID))).
112-
Format(db.ci)
113+
query, args, err := sq.Select("meta").
114+
From(db.table.Wallets).
115+
Where(sq.And{sq.Eq{"identity_hash": idHash}, sq.Eq{"wallet_id": wID}, sq.Eq{"role_id": roleID}}).
116+
PlaceholderFormat(db.pf).ToSql()
117+
if err != nil {
118+
return nil, errors.Wrapf(err, "failed building query for meta [%v]", idHash)
119+
}
113120
result, err := common.QueryUnique[[]byte](db.readDB, query, args...)
114121
if err != nil {
115122
return nil, errors.Wrapf(err, "failed loading meta for id [%v]", idHash)
@@ -121,11 +128,14 @@ func (db *WalletStore) LoadMeta(ctx context.Context, identity token.Identity, wI
121128

122129
func (db *WalletStore) IdentityExists(ctx context.Context, identity token.Identity, wID driver.WalletID, roleID int) bool {
123130
idHash := identity.UniqueID()
124-
query, args := q.Select().
125-
FieldsByName("wallet_id").
126-
From(q.Table(db.table.Wallets)).
127-
Where(cond.And(cond.Eq("identity_hash", idHash), cond.Eq("wallet_id", wID), cond.Eq("role_id", roleID))).
128-
Format(db.ci)
131+
query, args, err := sq.Select("wallet_id").
132+
From(db.table.Wallets).
133+
Where(sq.And{sq.Eq{"identity_hash": idHash}, sq.Eq{"wallet_id": wID}, sq.Eq{"role_id": roleID}}).
134+
PlaceholderFormat(db.pf).ToSql()
135+
if err != nil {
136+
logger.Errorf("failed building query for wallet-identity [%s-%s]: %v", wID, idHash, err)
137+
return false
138+
}
129139
result, err := common.QueryUnique[driver.WalletID](db.readDB, query, args...)
130140
if err != nil {
131141
logger.Errorf("failed looking up wallet-identity [%s-%s]: %w", wID, idHash, err)

token/services/storage/db/sql/common/wallet_test_utils.go

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@ package common
77

88
import (
99
"database/sql"
10+
"regexp"
1011
"testing"
1112

1213
"github.com/DATA-DOG/go-sqlmock"
14+
sq "github.com/Masterminds/squirrel"
1315
"github.com/hyperledger-labs/fabric-token-sdk/token"
1416
"github.com/hyperledger-labs/fabric-token-sdk/token/services/storage/db/driver"
1517
"github.com/onsi/gomega"
1618
)
1719

18-
type walletStoreConstructor func(*sql.DB) *WalletStore
20+
type walletStoreConstructor func(*sql.DB, sq.PlaceholderFormat) *WalletStore
1921

20-
func TestGetWalletID(t *testing.T, store walletStoreConstructor) {
22+
func TestGetWalletID(t *testing.T, store walletStoreConstructor, pf sq.PlaceholderFormat) {
2123
gomega.RegisterTestingT(t)
2224
db, mockDB, err := sqlmock.New()
2325
gomega.Expect(err).ToNot(gomega.HaveOccurred())
@@ -26,37 +28,37 @@ func TestGetWalletID(t *testing.T, store walletStoreConstructor) {
2628
roleID := 5
2729
output := driver.WalletID("my wallet")
2830
mockDB.
29-
ExpectQuery("SELECT wallet_id FROM WALLETS WHERE \\(identity_hash = \\$1\\) AND \\(role_id = \\$2\\)").
31+
ExpectQuery(sqlPattern(pf, "SELECT wallet_id FROM WALLETS WHERE (identity_hash = ? AND role_id = ?)")).
3032
WithArgs(tokenID.UniqueID(), roleID).
31-
WillReturnRows(mockDB.NewRows([]string{"request"}).AddRow(output))
33+
WillReturnRows(mockDB.NewRows([]string{"wallet_id"}).AddRow(output))
3234

33-
actualWalletID, err := store(db).GetWalletID(t.Context(), tokenID, roleID)
35+
actualWalletID, err := store(db, pf).GetWalletID(t.Context(), tokenID, roleID)
3436

3537
gomega.Expect(mockDB.ExpectationsWereMet()).To(gomega.Succeed())
3638
gomega.Expect(err).ToNot(gomega.HaveOccurred())
3739
gomega.Expect(actualWalletID).To(gomega.Equal(output))
3840
}
3941

40-
func TestGetWalletIDs(t *testing.T, store walletStoreConstructor) {
42+
func TestGetWalletIDs(t *testing.T, store walletStoreConstructor, pf sq.PlaceholderFormat) {
4143
gomega.RegisterTestingT(t)
4244
db, mockDB, err := sqlmock.New()
4345
gomega.Expect(err).ToNot(gomega.HaveOccurred())
4446

4547
roleID := 5
4648
output := driver.WalletID("my wallet")
4749
mockDB.
48-
ExpectQuery("SELECT DISTINCT wallet_id FROM WALLETS WHERE role_id = \\$1").
50+
ExpectQuery(sqlPattern(pf, "SELECT DISTINCT wallet_id FROM WALLETS WHERE role_id = ?")).
4951
WithArgs(roleID).
5052
WillReturnRows(mockDB.NewRows([]string{"wallet_id"}).AddRow(output))
5153

52-
actualWalletIDs, err := store(db).GetWalletIDs(t.Context(), roleID)
54+
actualWalletIDs, err := store(db, pf).GetWalletIDs(t.Context(), roleID)
5355

5456
gomega.Expect(mockDB.ExpectationsWereMet()).To(gomega.Succeed())
5557
gomega.Expect(err).ToNot(gomega.HaveOccurred())
5658
gomega.Expect(actualWalletIDs).To(gomega.ConsistOf(output))
5759
}
5860

59-
func TestLoadMeta(t *testing.T, store walletStoreConstructor) {
61+
func TestLoadMeta(t *testing.T, store walletStoreConstructor, pf sq.PlaceholderFormat) {
6062
gomega.RegisterTestingT(t)
6163
db, mockDB, err := sqlmock.New()
6264
gomega.Expect(err).ToNot(gomega.HaveOccurred())
@@ -66,18 +68,18 @@ func TestLoadMeta(t *testing.T, store walletStoreConstructor) {
6668
walletID := driver.WalletID("my wallet")
6769
output := []byte("some meta data")
6870
mockDB.
69-
ExpectQuery("SELECT meta FROM WALLETS WHERE \\(identity_hash = \\$1\\) AND \\(wallet_id = \\$2\\) AND \\(role_id = \\$3\\)").
71+
ExpectQuery(sqlPattern(pf, "SELECT meta FROM WALLETS WHERE (identity_hash = ? AND wallet_id = ? AND role_id = ?)")).
7072
WithArgs(tokenID.UniqueID(), walletID, roleID).
7173
WillReturnRows(mockDB.NewRows([]string{"meta"}).AddRow(output))
7274

73-
actual, err := store(db).LoadMeta(t.Context(), tokenID, walletID, roleID)
75+
actual, err := store(db, pf).LoadMeta(t.Context(), tokenID, walletID, roleID)
7476

7577
gomega.Expect(mockDB.ExpectationsWereMet()).To(gomega.Succeed())
7678
gomega.Expect(err).ToNot(gomega.HaveOccurred())
7779
gomega.Expect(actual).To(gomega.Equal(output))
7880
}
7981

80-
func TestIdentityExists(t *testing.T, store walletStoreConstructor) {
82+
func TestIdentityExists(t *testing.T, store walletStoreConstructor, pf sq.PlaceholderFormat) {
8183
gomega.RegisterTestingT(t)
8284
db, mockDB, err := sqlmock.New()
8385
gomega.Expect(err).ToNot(gomega.HaveOccurred())
@@ -86,18 +88,17 @@ func TestIdentityExists(t *testing.T, store walletStoreConstructor) {
8688
roleID := 5
8789
walletID := driver.WalletID("my wallet")
8890
mockDB.
89-
ExpectQuery("SELECT wallet_id FROM WALLETS WHERE \\(identity_hash = \\$1\\) AND \\(wallet_id = \\$2\\) AND \\(role_id = \\$3\\)").
91+
ExpectQuery(sqlPattern(pf, "SELECT wallet_id FROM WALLETS WHERE (identity_hash = ? AND wallet_id = ? AND role_id = ?)")).
9092
WithArgs(tokenID.UniqueID(), walletID, roleID).
9193
WillReturnRows(mockDB.NewRows([]string{"wallet_id"}).AddRow(walletID))
9294

93-
exists := store(db).IdentityExists(t.Context(), tokenID, walletID, roleID)
95+
exists := store(db, pf).IdentityExists(t.Context(), tokenID, walletID, roleID)
9496

9597
gomega.Expect(mockDB.ExpectationsWereMet()).To(gomega.Succeed())
96-
gomega.Expect(err).ToNot(gomega.HaveOccurred())
9798
gomega.Expect(exists).To(gomega.BeTrue())
9899
}
99100

100-
func TestStoreIdentity(t *testing.T, store walletStoreConstructor) {
101+
func TestStoreIdentity(t *testing.T, store walletStoreConstructor, pf sq.PlaceholderFormat) {
101102
gomega.RegisterTestingT(t)
102103
db, mockDB, err := sqlmock.New()
103104
gomega.Expect(err).ToNot(gomega.HaveOccurred())
@@ -107,13 +108,11 @@ func TestStoreIdentity(t *testing.T, store walletStoreConstructor) {
107108
walletID := driver.WalletID("my wallet")
108109
roleID := 5
109110

110-
mockDB.ExpectExec("INSERT INTO WALLETS "+
111-
"\\(identity_hash, meta, wallet_id, role_id, created_at, enrollment_id\\) "+
112-
"VALUES \\(\\$1, \\$2, \\$3, \\$4, \\$5, \\$6\\) ON CONFLICT DO NOTHING").
111+
mockDB.ExpectExec(sqlPattern(pf, "INSERT INTO WALLETS (identity_hash,meta,wallet_id,role_id,created_at,enrollment_id) VALUES (?,?,?,?,?,?) ON CONFLICT DO NOTHING")).
113112
WithArgs(tokenID.UniqueID(), []uint8(nil), walletID, roleID, sqlmock.AnyArg(), eID).
114113
WillReturnResult(sqlmock.NewResult(1, 1))
115114

116-
err = store(db).StoreIdentity(t.Context(), tokenID, eID, walletID, roleID, nil)
115+
err = store(db, pf).StoreIdentity(t.Context(), tokenID, eID, walletID, roleID, nil)
117116

118117
gomega.Expect(mockDB.ExpectationsWereMet()).To(gomega.Succeed())
119118
gomega.Expect(err).ToNot(gomega.HaveOccurred())
@@ -129,9 +128,9 @@ func TestStoreIdentityIdempotent(t *testing.T, store walletStoreConstructor) {
129128
walletID := driver.WalletID("my wallet")
130129
roleID := 5
131130

132-
insertQuery := "INSERT INTO WALLETS " +
133-
"\\(identity_hash, meta, wallet_id, role_id, created_at, enrollment_id\\) " +
134-
"VALUES \\(\\$1, \\$2, \\$3, \\$4, \\$5, \\$6\\) ON CONFLICT DO NOTHING"
131+
// Use Dollar format for mock patterns — tests idempotency, not SQL dialect
132+
pf := sq.Dollar
133+
insertQuery := sqlPattern(pf, "INSERT INTO WALLETS (identity_hash,meta,wallet_id,role_id,created_at,enrollment_id) VALUES (?,?,?,?,?,?) ON CONFLICT DO NOTHING")
135134

136135
// First call: row inserted (1 row affected)
137136
mockDB.ExpectExec(insertQuery).
@@ -143,7 +142,7 @@ func TestStoreIdentityIdempotent(t *testing.T, store walletStoreConstructor) {
143142
WithArgs(tokenID.UniqueID(), []uint8(nil), walletID, roleID, sqlmock.AnyArg(), eID).
144143
WillReturnResult(sqlmock.NewResult(0, 0))
145144

146-
s := store(db)
145+
s := store(db, pf)
147146
err = s.StoreIdentity(t.Context(), tokenID, eID, walletID, roleID, nil)
148147
gomega.Expect(err).ToNot(gomega.HaveOccurred())
149148

@@ -152,3 +151,11 @@ func TestStoreIdentityIdempotent(t *testing.T, store walletStoreConstructor) {
152151

153152
gomega.Expect(mockDB.ExpectationsWereMet()).To(gomega.Succeed())
154153
}
154+
155+
func sqlPattern(pf sq.PlaceholderFormat, query string) string {
156+
replaced, err := pf.ReplacePlaceholders(query)
157+
if err != nil {
158+
return query
159+
}
160+
return regexp.QuoteMeta(replaced)
161+
}

0 commit comments

Comments
 (0)