From 800d4ef06370658db6592f36afca6021c21d6126 Mon Sep 17 00:00:00 2001 From: Marcelo Fuentes Date: Sat, 11 Jun 2022 21:56:51 -0400 Subject: [PATCH 1/3] fix: handle unique constraint for domain + ip --- server/grpc/grpc.go | 2 +- storage/sqlite/sqlite.go | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index eabfa71..bbc0d08 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -61,7 +61,7 @@ func (srv *Server) PutRecord(ctx context.Context, r *pb.Record) (*pb.Record, err }) if err != nil { - logEntry.Error("unable to store data") + logEntry.WithField("reason", err).Error("unable to store data") return nil, err } diff --git a/storage/sqlite/sqlite.go b/storage/sqlite/sqlite.go index 5fa9c70..4083bc0 100644 --- a/storage/sqlite/sqlite.go +++ b/storage/sqlite/sqlite.go @@ -6,9 +6,15 @@ import ( "github.com/jmoiron/sqlx" "github.com/mfuentesg/localdns/storage" - _ "modernc.org/sqlite" // sqlite driver + "modernc.org/sqlite" ) +var ( + ErrRecordAlreadyExists = errors.New("record already exists") +) + +const SQLITE_CONSTRAINT_UNIQUE = 2067 + type SQLite struct { db *sqlx.DB } @@ -23,12 +29,17 @@ func New(dsn string) (*SQLite, error) { } func (sq *SQLite) Put(r storage.Record) (string, error) { - query := `insert or replace into records( + query := `insert into records( domain, ipv4, ipv6, ttl, type ) values(?, ?, ?, ?, ?) returning id` var id string err := sq.db.QueryRow(query, r.Domain, r.IPv4, r.IPv6, r.TTL, r.Type).Scan(&id) + + errCode := err.(*sqlite.Error).Code() + if errCode == SQLITE_CONSTRAINT_UNIQUE { + return "", ErrRecordAlreadyExists + } return id, err } From ed101874a7aa18c229c0dc70db07298c5c4975f1 Mon Sep 17 00:00:00 2001 From: Marcelo Fuentes Date: Sat, 11 Jun 2022 22:02:07 -0400 Subject: [PATCH 2/3] fix: change constant name using camel case --- storage/sqlite/sqlite.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/storage/sqlite/sqlite.go b/storage/sqlite/sqlite.go index 4083bc0..a66bfac 100644 --- a/storage/sqlite/sqlite.go +++ b/storage/sqlite/sqlite.go @@ -13,7 +13,11 @@ var ( ErrRecordAlreadyExists = errors.New("record already exists") ) -const SQLITE_CONSTRAINT_UNIQUE = 2067 +// SQLite constraint codes + +const ( + ConstraintUnique = 2067 +) type SQLite struct { db *sqlx.DB @@ -37,7 +41,7 @@ func (sq *SQLite) Put(r storage.Record) (string, error) { err := sq.db.QueryRow(query, r.Domain, r.IPv4, r.IPv6, r.TTL, r.Type).Scan(&id) errCode := err.(*sqlite.Error).Code() - if errCode == SQLITE_CONSTRAINT_UNIQUE { + if errCode == ConstraintUnique { return "", ErrRecordAlreadyExists } return id, err From ee0c08a784c479fa5d63437579ae9306a4c78256 Mon Sep 17 00:00:00 2001 From: Marcelo Fuentes Date: Sat, 11 Jun 2022 22:05:13 -0400 Subject: [PATCH 3/3] add reference link to sqlite codes --- storage/sqlite/sqlite.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/storage/sqlite/sqlite.go b/storage/sqlite/sqlite.go index a66bfac..7d08b59 100644 --- a/storage/sqlite/sqlite.go +++ b/storage/sqlite/sqlite.go @@ -14,9 +14,10 @@ var ( ) // SQLite constraint codes +// Reference: https://www.sqlite.org/rescode.html#pve const ( - ConstraintUnique = 2067 + ErrCodeConstraintUnique = 2067 ) type SQLite struct { @@ -41,7 +42,7 @@ func (sq *SQLite) Put(r storage.Record) (string, error) { err := sq.db.QueryRow(query, r.Domain, r.IPv4, r.IPv6, r.TTL, r.Type).Scan(&id) errCode := err.(*sqlite.Error).Code() - if errCode == ConstraintUnique { + if errCode == ErrCodeConstraintUnique { return "", ErrRecordAlreadyExists } return id, err