Skip to content

Commit

Permalink
✨ 支持设置 VARCHAR 类型大小是否为字符长度
Browse files Browse the repository at this point in the history
Signed-off-by: liutianqi <[email protected]>
  • Loading branch information
iTanken committed Jan 30, 2024
1 parent 0985273 commit d8b991d
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 15 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ func main() {
// oracle://user:[email protected]:1521/service
url := oracle.BuildUrl("127.0.0.1", "1521", "service", "user", "password", options)
dialector := oracle.New(oracle.Config{
DSN: url,
IgnoreCase: false, // query conditions are not case-sensitive
NamingCaseSensitive: true, // whether naming is case-sensitive
DSN: url,
IgnoreCase: false, // query conditions are not case-sensitive
NamingCaseSensitive: true, // whether naming is case-sensitive
VarcharSizeIsCharLength: true, // whether VARCHAR type size is character length, defaulting to byte length
})
db, err := gorm.Open(dialector, &gorm.Config{
SkipDefaultTransaction: true, // 是否禁用默认在事务中执行单次创建、更新、删除操作
Expand Down
15 changes: 13 additions & 2 deletions oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type Config struct {

IgnoreCase bool // warning: may cause performance issues
NamingCaseSensitive bool // whether naming is case-sensitive
// whether VARCHAR type size is character length, defaulting to byte length
VarcharSizeIsCharLength bool
}

type Dialector struct {
Expand Down Expand Up @@ -465,8 +467,17 @@ func (d Dialector) DataTypeOf(field *schema.Field) string {
}
}

if size > 0 && size <= 2000 {
sqlType = fmt.Sprintf("VARCHAR2(%d)", size)
if size > 0 && size <= 4000 {
// 默认情况下 VARCHAR2 可以指定一个不超过 4000 的正整数作为字节长度
if d.VarcharSizeIsCharLength {
if size*3 > 4000 {
sqlType = "CLOB"
} else {
sqlType = fmt.Sprintf("VARCHAR2(%d CHAR)", size) // 字符长度(size * 3)
}
} else {
sqlType = fmt.Sprintf("VARCHAR2(%d)", size)
}
} else {
sqlType = "CLOB"
}
Expand Down
87 changes: 77 additions & 10 deletions oracle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,21 @@ func init() {
}

func openTestConnection(ignoreCase, namingCase bool) (db *gorm.DB, err error) {
dsn := os.Getenv("GORM_ORA_DSN")
dsn := getTestDSN()

db, err = gorm.Open(New(Config{
DSN: dsn,
IgnoreCase: ignoreCase,
NamingCaseSensitive: namingCase,
}), getTestGormConfig())
if db != nil && err == nil {
log.Println("open oracle database connection success!")
}
return
}

func getTestDSN() (dsn string) {
dsn = os.Getenv("GORM_ORA_DSN")
if dsn == "" {
server := os.Getenv("GORM_ORA_SERVER")
port, _ := strconv.Atoi(os.Getenv("GORM_ORA_PORT"))
Expand Down Expand Up @@ -66,25 +80,21 @@ func openTestConnection(ignoreCase, namingCase bool) (db *gorm.DB, err error) {
"SSL": "false",
})
}
return
}

func getTestGormConfig() *gorm.Config {
logWriter := new(log.Logger)
logWriter.SetOutput(os.Stdout)
db, err = gorm.Open(New(Config{
DSN: dsn,
IgnoreCase: ignoreCase,
NamingCaseSensitive: namingCase,
}), &gorm.Config{

return &gorm.Config{
Logger: logger.New(
logWriter,
logger.Config{LogLevel: logger.Info},
),
DisableForeignKeyConstraintWhenMigrating: false,
IgnoreRelationshipsWhenMigrating: false,
})
if db != nil && err == nil {
log.Println("open oracle database connection success!")
}
return
}

func TestCountLimit0(t *testing.T) {
Expand Down Expand Up @@ -222,3 +232,60 @@ func TestGetStringExpr(t *testing.T) {
})
}
}

func TestVarcharSizeIsCharLength(t *testing.T) {
dsn := getTestDSN()

db, err := gorm.Open(New(Config{
DSN: dsn,
IgnoreCase: true,
NamingCaseSensitive: true,
VarcharSizeIsCharLength: true,
}), getTestGormConfig())
if db != nil && err == nil {
log.Println("open oracle database connection success!")
}

model := TestTableUserVarcharSize{}
migrator := db.Set("gorm:table_comments", "TestVarcharSizeIsCharLength").Migrator()
if migrator.HasTable(model) {
if err = migrator.DropTable(model); err != nil {
t.Fatalf("DropTable() error = %v", err)
}
}
if err = migrator.AutoMigrate(model); err != nil {
t.Fatalf("AutoMigrate() error = %v", err)
} else if err == nil {
t.Log("AutoMigrate() success!")
}

type args struct {
value string
}
tests := []struct {
name string
args args
wantErr bool
}{
{"50", args{strings.Repeat("姓名", 25)}, false},
{"60", args{strings.Repeat("姓名", 30)}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotErr := db.Create(&TestTableUserVarcharSize{TestTableUser{Name: tt.args.value}}).Error
if (gotErr != nil) != tt.wantErr {
t.Error(gotErr)
} else if gotErr != nil {
t.Log(gotErr)
}
})
}
}

type TestTableUserVarcharSize struct {
TestTableUser
}

func (TestTableUserVarcharSize) TableName() string {
return "test_user_varchar_size"
}

0 comments on commit d8b991d

Please sign in to comment.