Skip to content

Commit 7fc69dc

Browse files
committed
fix(server): sql server not allow multiple null
multiple null values for unique constrained column is not allowed on sqlserver Resolves #278
1 parent 8449821 commit 7fc69dc

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

server/db/providers/sql/provider.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package sql
22

33
import (
4+
"fmt"
45
"log"
56
"os"
67
"time"
@@ -21,6 +22,16 @@ type provider struct {
2122
db *gorm.DB
2223
}
2324

25+
const (
26+
phoneNumberIndexName = "UQ_phone_number"
27+
phoneNumberColumnName = "phone_number"
28+
)
29+
30+
type indexInfo struct {
31+
IndexName string `json:"index_name"`
32+
ColumnName string `json:"column_name"`
33+
}
34+
2435
// NewProvider returns a new SQL provider
2536
func NewProvider() (*provider, error) {
2637
var sqlDB *gorm.DB
@@ -65,6 +76,32 @@ func NewProvider() (*provider, error) {
6576
if err != nil {
6677
return nil, err
6778
}
79+
80+
// unique constraint on phone number does not work with multiple null values for sqlserver
81+
// for more information check https://stackoverflow.com/a/767702
82+
if dbType == constants.DbTypeSqlserver {
83+
var indexInfos []indexInfo
84+
// remove index on phone number if present with different name
85+
res := sqlDB.Raw("SELECT i.name AS index_name, i.type_desc AS index_algorithm, CASE i.is_unique WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS is_unique, ac.Name AS column_name FROM sys.tables AS t INNER JOIN sys.indexes AS i ON t.object_id = i.object_id INNER JOIN sys.index_columns AS ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id INNER JOIN sys.all_columns AS ac ON ic.object_id = ac.object_id AND ic.column_id = ac.column_id WHERE t.name = 'authorizer_users' AND SCHEMA_NAME(t.schema_id) = 'dbo';").Scan(&indexInfos)
86+
if res.Error != nil {
87+
return nil, res.Error
88+
}
89+
90+
for _, val := range indexInfos {
91+
if val.ColumnName == phoneNumberColumnName && val.IndexName != phoneNumberIndexName {
92+
// drop index & create new
93+
if res := sqlDB.Exec(fmt.Sprintf(`ALTER TABLE authorizer_users DROP CONSTRAINT "%s";`, val.IndexName)); res.Error != nil {
94+
return nil, res.Error
95+
}
96+
97+
// create index
98+
if res := sqlDB.Exec(fmt.Sprintf("CREATE UNIQUE NONCLUSTERED INDEX %s ON authorizer_users(phone_number) WHERE phone_number IS NOT NULL;", phoneNumberIndexName)); res.Error != nil {
99+
return nil, res.Error
100+
}
101+
}
102+
}
103+
}
104+
68105
return &provider{
69106
db: sqlDB,
70107
}, nil

0 commit comments

Comments
 (0)