Add GaussDB Database Support (#7508)
* support gaussdb * use github CI * change function name * use gorm.io/driver/gaussdb --------- Co-authored-by: bing.ma <bing.ma@daocloud.io>
This commit is contained in:
parent
751a6dde7a
commit
991c2d4891
68
.github/workflows/tests.yml
vendored
68
.github/workflows/tests.yml
vendored
@ -240,3 +240,71 @@ jobs:
|
|||||||
|
|
||||||
- name: Tests
|
- name: Tests
|
||||||
run: GITHUB_ACTION=true GORM_DIALECT=tidb GORM_DSN="root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local" ./tests/tests_all.sh
|
run: GITHUB_ACTION=true GORM_DIALECT=tidb GORM_DSN="root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local" ./tests/tests_all.sh
|
||||||
|
|
||||||
|
gaussdb:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
dbversion: ['opengauss/opengauss:7.0.0-RC1.B023']
|
||||||
|
go: ['1.23', '1.24']
|
||||||
|
platform: [ubuntu-latest] # can not run in macOS and Windows
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
services:
|
||||||
|
gaussdb:
|
||||||
|
image: ${{ matrix.dbversion }}
|
||||||
|
env:
|
||||||
|
# GaussDB has password limitations
|
||||||
|
GS_PASSWORD: Gaussdb@123
|
||||||
|
TZ: Asia/Shanghai
|
||||||
|
ports:
|
||||||
|
- 9950:5432
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set up Go 1.x
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go }}
|
||||||
|
|
||||||
|
- name: Check out code into the Go module directory
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Waiting for GaussDB to be ready
|
||||||
|
run: |
|
||||||
|
container_name=$(docker ps --filter "ancestor=opengauss/opengauss:7.0.0-RC1.B023" --format "{{.Names}}")
|
||||||
|
if [ -z "$container_name" ]; then
|
||||||
|
echo "Error: failed to find a container created from the 'opengauss/opengauss:7.0.0-RC1.B023' image."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
max_retries=12
|
||||||
|
retry_count=0
|
||||||
|
if [ -t 0 ]; then
|
||||||
|
TTY_FLAG="-t"
|
||||||
|
else
|
||||||
|
TTY_FLAG=""
|
||||||
|
fi
|
||||||
|
while [ $retry_count -lt $max_retries ]; do
|
||||||
|
if docker exec -i "${container_name}" bash -c "su - omm -c 'gsql -U omm -c \"select 1;\"'"
|
||||||
|
then
|
||||||
|
echo "Creating database gorm..."
|
||||||
|
sql_file='/tmp/create_database.sql'
|
||||||
|
echo "CREATE DATABASE gorm DBCOMPATIBILITY 'PG';" > ${sql_file}
|
||||||
|
docker cp "${sql_file}" "${container_name}":"${sql_file}"
|
||||||
|
docker exec -i ${TTY_FLAG} "${container_name}" bash -c "su - omm -c 'gsql -U omm -f ${sql_file}'"
|
||||||
|
echo "Database initialization completed."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Waiting for database to be ready... (attempt $((retry_count + 1))/$max_retries)"
|
||||||
|
sleep 10
|
||||||
|
((++retry_count))
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
- name: go mod package cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }}
|
||||||
|
|
||||||
|
- name: Tests
|
||||||
|
run: GITHUB_ACTION=true GORM_DIALECT=gaussdb GORM_DSN="user=gaussdb password=Gaussdb@123 dbname=gorm host=localhost port=9950 sslmode=disable TimeZone=Asia/Shanghai" ./tests/tests_all.sh
|
@ -206,9 +206,9 @@ func TestDeleteSliceWithAssociations(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only sqlite, postgres, sqlserver support returning
|
// only sqlite, postgres, gaussdb, sqlserver support returning
|
||||||
func TestSoftDeleteReturning(t *testing.T) {
|
func TestSoftDeleteReturning(t *testing.T) {
|
||||||
if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "sqlserver" {
|
if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" && DB.Dialector.Name() != "sqlserver" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ func TestSoftDeleteReturning(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteReturning(t *testing.T) {
|
func TestDeleteReturning(t *testing.T) {
|
||||||
if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "sqlserver" {
|
if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" && DB.Dialector.Name() != "sqlserver" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ func TestSupportedDialectorWithErrDuplicatedKey(t *testing.T) {
|
|||||||
t.Fatalf("failed to connect database, got error %v", err)
|
t.Fatalf("failed to connect database, got error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialectors := map[string]bool{"sqlite": true, "postgres": true, "mysql": true, "sqlserver": true}
|
dialectors := map[string]bool{"sqlite": true, "postgres": true, "gaussdb": true, "mysql": true, "sqlserver": true}
|
||||||
if supported, found := dialectors[db.Dialector.Name()]; !(found && supported) {
|
if supported, found := dialectors[db.Dialector.Name()]; !(found && supported) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ func TestSupportedDialectorWithErrForeignKeyViolated(t *testing.T) {
|
|||||||
t.Fatalf("failed to connect database, got error %v", err)
|
t.Fatalf("failed to connect database, got error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialectors := map[string]bool{"sqlite": true, "postgres": true, "mysql": true, "sqlserver": true}
|
dialectors := map[string]bool{"sqlite": true, "postgres": true, "gaussdb": true, "mysql": true, "sqlserver": true}
|
||||||
if supported, found := dialectors[db.Dialector.Name()]; !(found && supported) {
|
if supported, found := dialectors[db.Dialector.Name()]; !(found && supported) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
248
tests/gaussdb_test.go
Normal file
248
tests/gaussdb_test.go
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
package tests_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/lib/pq"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
|
. "gorm.io/gorm/utils/tests"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGaussDBReturningIDWhichHasStringType(t *testing.T) {
|
||||||
|
t.Skipf("This test case skipped, because of gaussdb not support pgcrypto extension and gen_random_uuid() function")
|
||||||
|
if DB.Dialector.Name() != "gaussdb" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Yasuo struct {
|
||||||
|
// TODO: function gen_random_uuid() does not exist
|
||||||
|
ID string `gorm:"default:gen_random_uuid()"`
|
||||||
|
Name string
|
||||||
|
CreatedAt time.Time `gorm:"type:TIMESTAMP WITHOUT TIME ZONE"`
|
||||||
|
UpdatedAt time.Time `gorm:"type:TIMESTAMP WITHOUT TIME ZONE;default:current_timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Exec("CREATE EXTENSION IF NOT EXISTS pgcrypto;").Error; err != nil {
|
||||||
|
t.Errorf("Failed to create extension pgcrypto, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Migrator().DropTable(&Yasuo{})
|
||||||
|
|
||||||
|
if err := DB.AutoMigrate(&Yasuo{}); err != nil {
|
||||||
|
t.Fatalf("Failed to migrate for uuid default value, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
yasuo := Yasuo{Name: "jinzhu"}
|
||||||
|
if err := DB.Create(&yasuo).Error; err != nil {
|
||||||
|
t.Fatalf("should be able to create data, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if yasuo.ID == "" {
|
||||||
|
t.Fatal("should be able to has ID, but got zero value")
|
||||||
|
}
|
||||||
|
|
||||||
|
var result Yasuo
|
||||||
|
if err := DB.First(&result, "id = ?", yasuo.ID).Error; err != nil || yasuo.Name != "jinzhu" {
|
||||||
|
t.Errorf("No error should happen, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Where("id = $1", yasuo.ID).First(&Yasuo{}).Error; err != nil || yasuo.Name != "jinzhu" {
|
||||||
|
t.Errorf("No error should happen, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
yasuo.Name = "jinzhu1"
|
||||||
|
if err := DB.Save(&yasuo).Error; err != nil {
|
||||||
|
t.Errorf("Failed to update date, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.First(&result, "id = ?", yasuo.ID).Error; err != nil || yasuo.Name != "jinzhu1" {
|
||||||
|
t.Errorf("No error should happen, but got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGaussDB(t *testing.T) {
|
||||||
|
t.Skipf("This test case skipped, because of gaussdb not support pgcrypto extension and gen_random_uuid() function")
|
||||||
|
if DB.Dialector.Name() != "gaussdb" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Harumph struct {
|
||||||
|
gorm.Model
|
||||||
|
Name string `gorm:"check:name_checker,name <> ''"`
|
||||||
|
// TODO: function gen_random_uuid() does not exist
|
||||||
|
Test uuid.UUID `gorm:"type:uuid;not null;default:gen_random_uuid()"`
|
||||||
|
CreatedAt time.Time `gorm:"type:TIMESTAMP WITHOUT TIME ZONE"`
|
||||||
|
UpdatedAt time.Time `gorm:"type:TIMESTAMP WITHOUT TIME ZONE;default:current_timestamp"`
|
||||||
|
Things pq.StringArray `gorm:"type:text[]"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Exec("CREATE EXTENSION IF NOT EXISTS pgcrypto;").Error; err != nil {
|
||||||
|
t.Errorf("Failed to create extension pgcrypto, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Migrator().DropTable(&Harumph{})
|
||||||
|
|
||||||
|
if err := DB.AutoMigrate(&Harumph{}); err != nil {
|
||||||
|
t.Fatalf("Failed to migrate for uuid default value, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
harumph := Harumph{}
|
||||||
|
if err := DB.Create(&harumph).Error; err == nil {
|
||||||
|
t.Fatalf("should failed to create data, name can't be blank")
|
||||||
|
}
|
||||||
|
|
||||||
|
harumph = Harumph{Name: "jinzhu"}
|
||||||
|
if err := DB.Create(&harumph).Error; err != nil {
|
||||||
|
t.Fatalf("should be able to create data, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result Harumph
|
||||||
|
if err := DB.First(&result, "id = ?", harumph.ID).Error; err != nil || harumph.Name != "jinzhu" {
|
||||||
|
t.Errorf("No error should happen, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Where("id = $1", harumph.ID).First(&Harumph{}).Error; err != nil || harumph.Name != "jinzhu" {
|
||||||
|
t.Errorf("No error should happen, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
harumph.Name = "jinzhu1"
|
||||||
|
if err := DB.Save(&harumph).Error; err != nil {
|
||||||
|
t.Errorf("Failed to update date, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.First(&result, "id = ?", harumph.ID).Error; err != nil || harumph.Name != "jinzhu1" {
|
||||||
|
t.Errorf("No error should happen, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Migrator().DropTable("log_usage")
|
||||||
|
|
||||||
|
if err := DB.Exec(`
|
||||||
|
CREATE TABLE public.log_usage (
|
||||||
|
log_id bigint NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE public.log_usage ALTER COLUMN log_id ADD GENERATED BY DEFAULT AS IDENTITY (
|
||||||
|
SEQUENCE NAME public.log_usage_log_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1
|
||||||
|
);
|
||||||
|
`).Error; err != nil {
|
||||||
|
t.Fatalf("failed to create table, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
columns, err := DB.Migrator().ColumnTypes("log_usage")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to get columns, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hasLogID := false
|
||||||
|
for _, column := range columns {
|
||||||
|
if column.Name() == "log_id" {
|
||||||
|
hasLogID = true
|
||||||
|
autoIncrement, ok := column.AutoIncrement()
|
||||||
|
if !ok || !autoIncrement {
|
||||||
|
t.Fatalf("column log_id should be auto incrementment")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasLogID {
|
||||||
|
t.Fatalf("failed to found column log_id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGaussDBMany2ManyWithDefaultValueUUID(t *testing.T) {
|
||||||
|
t.Skipf("This test case skipped, because of gaussdb does not have 'uuid-ossp' extension")
|
||||||
|
if DB.Dialector.Name() != "gaussdb" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Exec(`create extension if not exists "uuid-ossp"`).Error; err != nil {
|
||||||
|
t.Fatalf("Failed to create 'uuid-ossp' extension, but got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Migrator().DropTable(&Post{}, &Category{}, "post_categories")
|
||||||
|
DB.AutoMigrate(&Post{}, &Category{})
|
||||||
|
|
||||||
|
post := Post{
|
||||||
|
Title: "Hello World",
|
||||||
|
Categories: []*Category{
|
||||||
|
{Title: "Coding"},
|
||||||
|
{Title: "Golang"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Create(&post).Error; err != nil {
|
||||||
|
t.Errorf("Failed, got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGaussDBOnConstraint(t *testing.T) {
|
||||||
|
t.Skipf("This test case skipped, because of gaussdb not support 'ON CONSTRAINT' statement")
|
||||||
|
if DB.Dialector.Name() != "gaussdb" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Thing struct {
|
||||||
|
gorm.Model
|
||||||
|
SomeID string
|
||||||
|
OtherID string
|
||||||
|
Data string
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Migrator().DropTable(&Thing{})
|
||||||
|
DB.Migrator().CreateTable(&Thing{})
|
||||||
|
if err := DB.Exec("ALTER TABLE things ADD CONSTRAINT some_id_other_id_unique UNIQUE (some_id, other_id)").Error; err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
thing := Thing{
|
||||||
|
SomeID: "1234",
|
||||||
|
OtherID: "1234",
|
||||||
|
Data: "something",
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Create(&thing)
|
||||||
|
|
||||||
|
thing2 := Thing{
|
||||||
|
SomeID: "1234",
|
||||||
|
OtherID: "1234",
|
||||||
|
Data: "something else",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := DB.Clauses(clause.OnConflict{
|
||||||
|
OnConstraint: "some_id_other_id_unique",
|
||||||
|
UpdateAll: true,
|
||||||
|
}).Create(&thing2)
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Errorf("creating second thing: %v", result.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var things []Thing
|
||||||
|
if err := DB.Find(&things).Error; err != nil {
|
||||||
|
t.Errorf("Failed, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(things) > 1 {
|
||||||
|
t.Errorf("expected 1 thing got more")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGaussDBAlterColumnDataType(t *testing.T) {
|
||||||
|
if DB.Dialector.Name() != "gaussdb" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
DB.Migrator().DropTable(&Company{})
|
||||||
|
DB.AutoMigrate(Company{})
|
||||||
|
if err := DB.Table("companies").Migrator().AlterColumn(CompanyNew{}, "name"); err != nil {
|
||||||
|
t.Fatalf("failed to alter column from string to int, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.AutoMigrate(Company{})
|
||||||
|
}
|
@ -7,6 +7,7 @@ require (
|
|||||||
github.com/jinzhu/now v1.1.5
|
github.com/jinzhu/now v1.1.5
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
|
gorm.io/driver/gaussdb v0.1.0
|
||||||
gorm.io/driver/mysql v1.6.0
|
gorm.io/driver/mysql v1.6.0
|
||||||
gorm.io/driver/postgres v1.6.0
|
gorm.io/driver/postgres v1.6.0
|
||||||
gorm.io/driver/sqlite v1.6.0
|
gorm.io/driver/sqlite v1.6.0
|
||||||
@ -16,6 +17,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
|
github.com/HuaweiCloudDeveloper/gaussdb-go v1.0.0-rc1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.9.2 // indirect
|
github.com/go-sql-driver/mysql v1.9.2 // indirect
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||||
@ -30,10 +32,11 @@ require (
|
|||||||
github.com/microsoft/go-mssqldb v1.8.2 // indirect
|
github.com/microsoft/go-mssqldb v1.8.2 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||||
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
golang.org/x/crypto v0.38.0 // indirect
|
golang.org/x/crypto v0.38.0 // indirect
|
||||||
golang.org/x/sync v0.14.0 // indirect
|
golang.org/x/sync v0.14.0 // indirect
|
||||||
golang.org/x/text v0.25.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace gorm.io/gorm => ../
|
replace gorm.io/gorm => ../
|
@ -12,6 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gorm.io/driver/gaussdb"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@ -82,8 +83,8 @@ func TestMigrate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAutoMigrateInt8PG(t *testing.T) {
|
func TestAutoMigrateInt8PGAndGaussDB(t *testing.T) {
|
||||||
if DB.Dialector.Name() != "postgres" {
|
if DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +183,94 @@ func TestAutoMigrateNullable(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSmartMigrateColumn(t *testing.T) {
|
func TestSmartMigrateColumn(t *testing.T) {
|
||||||
fullSupported := map[string]bool{"mysql": true, "postgres": true}[DB.Dialector.Name()]
|
fullSupported := map[string]bool{"mysql": true, "postgres": true, "gaussdb": true}[DB.Dialector.Name()]
|
||||||
|
|
||||||
|
type UserMigrateColumn struct {
|
||||||
|
ID uint
|
||||||
|
Name string
|
||||||
|
Salary float64
|
||||||
|
Birthday time.Time `gorm:"precision:4"`
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Migrator().DropTable(&UserMigrateColumn{})
|
||||||
|
|
||||||
|
DB.AutoMigrate(&UserMigrateColumn{})
|
||||||
|
|
||||||
|
type UserMigrateColumn2 struct {
|
||||||
|
ID uint
|
||||||
|
Name string `gorm:"size:128"`
|
||||||
|
Salary float64 `gorm:"precision:2"`
|
||||||
|
Birthday time.Time `gorm:"precision:2"`
|
||||||
|
NameIgnoreMigration string `gorm:"size:100"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("user_migrate_columns").AutoMigrate(&UserMigrateColumn2{}); err != nil {
|
||||||
|
t.Fatalf("failed to auto migrate, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
columnTypes, err := DB.Table("user_migrate_columns").Migrator().ColumnTypes(&UserMigrateColumn{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to get column types, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, columnType := range columnTypes {
|
||||||
|
switch columnType.Name() {
|
||||||
|
case "name":
|
||||||
|
if length, _ := columnType.Length(); (fullSupported || length != 0) && length != 128 {
|
||||||
|
t.Fatalf("name's length should be 128, but got %v", length)
|
||||||
|
}
|
||||||
|
case "salary":
|
||||||
|
if precision, o, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 2 {
|
||||||
|
t.Fatalf("salary's precision should be 2, but got %v %v", precision, o)
|
||||||
|
}
|
||||||
|
case "birthday":
|
||||||
|
if precision, _, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 2 {
|
||||||
|
t.Fatalf("birthday's precision should be 2, but got %v", precision)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserMigrateColumn3 struct {
|
||||||
|
ID uint
|
||||||
|
Name string `gorm:"size:256"`
|
||||||
|
Salary float64 `gorm:"precision:3"`
|
||||||
|
Birthday time.Time `gorm:"precision:3"`
|
||||||
|
NameIgnoreMigration string `gorm:"size:128;-:migration"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("user_migrate_columns").AutoMigrate(&UserMigrateColumn3{}); err != nil {
|
||||||
|
t.Fatalf("failed to auto migrate, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
columnTypes, err = DB.Table("user_migrate_columns").Migrator().ColumnTypes(&UserMigrateColumn{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to get column types, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, columnType := range columnTypes {
|
||||||
|
switch columnType.Name() {
|
||||||
|
case "name":
|
||||||
|
if length, _ := columnType.Length(); (fullSupported || length != 0) && length != 256 {
|
||||||
|
t.Fatalf("name's length should be 128, but got %v", length)
|
||||||
|
}
|
||||||
|
case "salary":
|
||||||
|
if precision, _, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 3 {
|
||||||
|
t.Fatalf("salary's precision should be 2, but got %v", precision)
|
||||||
|
}
|
||||||
|
case "birthday":
|
||||||
|
if precision, _, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 3 {
|
||||||
|
t.Fatalf("birthday's precision should be 2, but got %v", precision)
|
||||||
|
}
|
||||||
|
case "name_ignore_migration":
|
||||||
|
if length, _ := columnType.Length(); (fullSupported || length != 0) && length != 100 {
|
||||||
|
t.Fatalf("name_ignore_migration's length should still be 100 but got %v", length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSmartMigrateColumnGaussDB(t *testing.T) {
|
||||||
|
fullSupported := map[string]bool{"mysql": true, "gaussdb": true}[DB.Dialector.Name()]
|
||||||
|
|
||||||
type UserMigrateColumn struct {
|
type UserMigrateColumn struct {
|
||||||
ID uint
|
ID uint
|
||||||
@ -850,7 +938,7 @@ func TestMigrateColumnOrder(t *testing.T) {
|
|||||||
|
|
||||||
// https://github.com/go-gorm/gorm/issues/5047
|
// https://github.com/go-gorm/gorm/issues/5047
|
||||||
func TestMigrateSerialColumn(t *testing.T) {
|
func TestMigrateSerialColumn(t *testing.T) {
|
||||||
if DB.Dialector.Name() != "postgres" {
|
if DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,6 +1097,42 @@ func TestPrimarykeyID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrimarykeyIDGaussDB(t *testing.T) {
|
||||||
|
t.Skipf("This test case skipped, because of gaussdb not support uuid-ossp plugin (SQLSTATE 58P01)")
|
||||||
|
if DB.Dialector.Name() != "gaussdb" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type MissPKLanguage struct {
|
||||||
|
ID string `gorm:"type:uuid;default:uuid_generate_v4()"`
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type MissPKUser struct {
|
||||||
|
ID string `gorm:"type:uuid;default:uuid_generate_v4()"`
|
||||||
|
MissPKLanguages []MissPKLanguage `gorm:"many2many:miss_pk_user_languages;"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
err = DB.Migrator().DropTable(&MissPKUser{}, &MissPKLanguage{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("DropTable err:%v", err)
|
||||||
|
}
|
||||||
|
// TODO: ERROR: could not open extension control file: No such file or directory (SQLSTATE 58P01)
|
||||||
|
DB.Exec(`CREATE EXTENSION IF NOT EXISTS "uuid-ossp";`)
|
||||||
|
|
||||||
|
err = DB.AutoMigrate(&MissPKUser{}, &MissPKLanguage{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("AutoMigrate err:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// patch
|
||||||
|
err = DB.AutoMigrate(&MissPKUser{}, &MissPKLanguage{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("AutoMigrate err:%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCurrentTimestamp(t *testing.T) {
|
func TestCurrentTimestamp(t *testing.T) {
|
||||||
if DB.Dialector.Name() != "mysql" {
|
if DB.Dialector.Name() != "mysql" {
|
||||||
return
|
return
|
||||||
@ -1209,6 +1333,43 @@ func TestInvalidCachedPlanSimpleProtocol(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: ERROR: must have at least one column (SQLSTATE 0A000)
|
||||||
|
func TestInvalidCachedPlanSimpleProtocolGaussDB(t *testing.T) {
|
||||||
|
t.Skipf("This test case skipped, because of gaussdb not support creaing empty table(SQLSTATE 0A000)")
|
||||||
|
if DB.Dialector.Name() != "gaussdb" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := gorm.Open(gaussdb.Open(gaussdbDSN), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Open err:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Object1 struct{}
|
||||||
|
type Object2 struct {
|
||||||
|
Field1 string
|
||||||
|
}
|
||||||
|
type Object3 struct {
|
||||||
|
Field2 string
|
||||||
|
}
|
||||||
|
db.Migrator().DropTable("objects")
|
||||||
|
|
||||||
|
err = db.Table("objects").AutoMigrate(&Object1{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("AutoMigrate err:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.Table("objects").AutoMigrate(&Object2{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("AutoMigrate err:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.Table("objects").AutoMigrate(&Object3{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("AutoMigrate err:%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDifferentTypeWithoutDeclaredLength(t *testing.T) {
|
func TestDifferentTypeWithoutDeclaredLength(t *testing.T) {
|
||||||
type DiffType struct {
|
type DiffType struct {
|
||||||
ID uint
|
ID uint
|
||||||
@ -1249,7 +1410,7 @@ func TestDifferentTypeWithoutDeclaredLength(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMigrateArrayTypeModel(t *testing.T) {
|
func TestMigrateArrayTypeModel(t *testing.T) {
|
||||||
if DB.Dialector.Name() != "postgres" {
|
if DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1571,8 +1732,8 @@ func TestMigrateView(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMigrateExistingBoolColumnPG(t *testing.T) {
|
func TestMigrateExistingBoolColumnPGAndGaussDB(t *testing.T) {
|
||||||
if DB.Dialector.Name() != "postgres" {
|
if DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1965,7 +2126,7 @@ func TestAutoMigrateDecimal(t *testing.T) {
|
|||||||
`ALTER TABLE "migrate_decimal_columns" ALTER COLUMN "recid3" decimal(9,2) NOT NULL`,
|
`ALTER TABLE "migrate_decimal_columns" ALTER COLUMN "recid3" decimal(9,2) NOT NULL`,
|
||||||
}
|
}
|
||||||
decimalColumnsTest[MigrateDecimalColumn, MigrateDecimalColumn2](t, expectedSql)
|
decimalColumnsTest[MigrateDecimalColumn, MigrateDecimalColumn2](t, expectedSql)
|
||||||
} else if DB.Dialector.Name() == "postgres" {
|
} else if DB.Dialector.Name() == "postgres" || DB.Dialector.Name() == "gaussdb" {
|
||||||
type MigrateDecimalColumn struct {
|
type MigrateDecimalColumn struct {
|
||||||
RecID1 int64 `gorm:"column:recid1;type:numeric(9,0);not null" json:"recid1"`
|
RecID1 int64 `gorm:"column:recid1;type:numeric(9,0);not null" json:"recid1"`
|
||||||
RecID2 int64 `gorm:"column:recid2;type:numeric(8);not null" json:"recid2"`
|
RecID2 int64 `gorm:"column:recid2;type:numeric(8);not null" json:"recid2"`
|
||||||
|
@ -41,7 +41,7 @@ func TestManyToManyWithMultiPrimaryKeys(t *testing.T) {
|
|||||||
t.Skip("skip sqlite, sqlserver due to it doesn't support multiple primary keys with auto increment")
|
t.Skip("skip sqlite, sqlserver due to it doesn't support multiple primary keys with auto increment")
|
||||||
}
|
}
|
||||||
|
|
||||||
if name := DB.Dialector.Name(); name == "postgres" || name == "mysql" {
|
if name := DB.Dialector.Name(); name == "postgres" || name == "mysql" || name == "gaussdb" {
|
||||||
stmt := gorm.Statement{DB: DB}
|
stmt := gorm.Statement{DB: DB}
|
||||||
stmt.Parse(&Blog{})
|
stmt.Parse(&Blog{})
|
||||||
stmt.Schema.LookUpField("ID").Unique = true
|
stmt.Schema.LookUpField("ID").Unique = true
|
||||||
@ -142,6 +142,9 @@ func TestManyToManyWithCustomizedForeignKeys(t *testing.T) {
|
|||||||
if name := DB.Dialector.Name(); name == "postgres" {
|
if name := DB.Dialector.Name(); name == "postgres" {
|
||||||
t.Skip("skip postgres due to it only allow unique constraint matching given keys")
|
t.Skip("skip postgres due to it only allow unique constraint matching given keys")
|
||||||
}
|
}
|
||||||
|
if name := DB.Dialector.Name(); name == "gaussdb" {
|
||||||
|
t.Skip("skip gaussdb due to it only allow unique constraint matching given keys")
|
||||||
|
}
|
||||||
|
|
||||||
DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags")
|
DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags")
|
||||||
if err := DB.AutoMigrate(&Blog{}, &Tag{}); err != nil {
|
if err := DB.AutoMigrate(&Blog{}, &Tag{}); err != nil {
|
||||||
@ -268,6 +271,10 @@ func TestManyToManyWithCustomizedForeignKeys2(t *testing.T) {
|
|||||||
t.Skip("skip postgres due to it only allow unique constraint matching given keys")
|
t.Skip("skip postgres due to it only allow unique constraint matching given keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if name := DB.Dialector.Name(); name == "gaussdb" {
|
||||||
|
t.Skip("skip gaussdb due to it only allow unique constraint matching given keys")
|
||||||
|
}
|
||||||
|
|
||||||
DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags")
|
DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags")
|
||||||
if err := DB.AutoMigrate(&Blog{}, &Tag{}); err != nil {
|
if err := DB.AutoMigrate(&Blog{}, &Tag{}); err != nil {
|
||||||
t.Fatalf("Failed to auto migrate, got error: %v", err)
|
t.Fatalf("Failed to auto migrate, got error: %v", err)
|
||||||
|
@ -45,7 +45,7 @@ type SerializerPostgresStruct struct {
|
|||||||
func (*SerializerPostgresStruct) TableName() string { return "serializer_structs" }
|
func (*SerializerPostgresStruct) TableName() string { return "serializer_structs" }
|
||||||
|
|
||||||
func adaptorSerializerModel(s *SerializerStruct) interface{} {
|
func adaptorSerializerModel(s *SerializerStruct) interface{} {
|
||||||
if DB.Dialector.Name() == "postgres" {
|
if DB.Dialector.Name() == "postgres" || DB.Dialector.Name() == "gaussdb" {
|
||||||
sps := SerializerPostgresStruct(*s)
|
sps := SerializerPostgresStruct(*s)
|
||||||
return &sps
|
return &sps
|
||||||
}
|
}
|
||||||
|
@ -487,7 +487,7 @@ func replaceQuoteInSQL(sql string) string {
|
|||||||
|
|
||||||
// convert dialect special quote into double quote
|
// convert dialect special quote into double quote
|
||||||
switch DB.Dialector.Name() {
|
switch DB.Dialector.Name() {
|
||||||
case "postgres":
|
case "postgres", "gaussdb":
|
||||||
sql = strings.ReplaceAll(sql, `"`, `"`)
|
sql = strings.ReplaceAll(sql, `"`, `"`)
|
||||||
case "mysql", "sqlite":
|
case "mysql", "sqlite":
|
||||||
sql = strings.ReplaceAll(sql, "`", `"`)
|
sql = strings.ReplaceAll(sql, "`", `"`)
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"gorm.io/driver/gaussdb"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/schema"
|
"gorm.io/gorm/schema"
|
||||||
@ -251,6 +252,82 @@ func TestPostgresTableWithIdentifierLength(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGaussDBTableWithIdentifierLength(t *testing.T) {
|
||||||
|
if DB.Dialector.Name() != "gaussdb" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type LongString struct {
|
||||||
|
ThisIsAVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString string `gorm:"unique"`
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("default", func(t *testing.T) {
|
||||||
|
db, _ := gorm.Open(gaussdb.Open(gaussdbDSN), &gorm.Config{})
|
||||||
|
user, err := schema.Parse(&LongString{}, &sync.Map{}, db.Config.NamingStrategy)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse user unique, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
constraints := user.ParseUniqueConstraints()
|
||||||
|
if len(constraints) != 1 {
|
||||||
|
t.Fatalf("failed to find unique constraint, got %v", constraints)
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range constraints {
|
||||||
|
if len(key) != 63 {
|
||||||
|
t.Errorf("failed to find unique constraint, got %v", constraints)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("naming strategy", func(t *testing.T) {
|
||||||
|
db, _ := gorm.Open(gaussdb.Open(gaussdbDSN), &gorm.Config{
|
||||||
|
NamingStrategy: schema.NamingStrategy{},
|
||||||
|
})
|
||||||
|
|
||||||
|
user, err := schema.Parse(&LongString{}, &sync.Map{}, db.Config.NamingStrategy)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse user unique, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
constraints := user.ParseUniqueConstraints()
|
||||||
|
if len(constraints) != 1 {
|
||||||
|
t.Fatalf("failed to find unique constraint, got %v", constraints)
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range constraints {
|
||||||
|
if len(key) != 63 {
|
||||||
|
t.Errorf("failed to find unique constraint, got %v", constraints)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("namer", func(t *testing.T) {
|
||||||
|
uname := "custom_unique_name"
|
||||||
|
db, _ := gorm.Open(gaussdb.Open(gaussdbDSN), &gorm.Config{
|
||||||
|
NamingStrategy: mockUniqueNamingStrategy{
|
||||||
|
UName: uname,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
user, err := schema.Parse(&LongString{}, &sync.Map{}, db.Config.NamingStrategy)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse user unique, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
constraints := user.ParseUniqueConstraints()
|
||||||
|
if len(constraints) != 1 {
|
||||||
|
t.Fatalf("failed to find unique constraint, got %v", constraints)
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range constraints {
|
||||||
|
if key != uname {
|
||||||
|
t.Errorf("failed to find unique constraint, got %v", constraints)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type mockUniqueNamingStrategy struct {
|
type mockUniqueNamingStrategy struct {
|
||||||
UName string
|
UName string
|
||||||
schema.NamingStrategy
|
schema.NamingStrategy
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
dialects=("sqlite" "mysql" "postgres" "sqlserver" "tidb")
|
dialects=("sqlite" "mysql" "postgres" "gaussdb" "sqlserver" "tidb")
|
||||||
|
|
||||||
if [[ $(pwd) == *"gorm/tests"* ]]; then
|
if [[ $(pwd) == *"gorm/tests"* ]]; then
|
||||||
cd ..
|
cd ..
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/driver/gaussdb"
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
@ -21,6 +22,7 @@ var DB *gorm.DB
|
|||||||
var (
|
var (
|
||||||
mysqlDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local"
|
mysqlDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local"
|
||||||
postgresDSN = "user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai"
|
postgresDSN = "user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai"
|
||||||
|
gaussdbDSN = "user=gaussdb password=Gaussdb@123 dbname=gorm host=localhost port=9950 sslmode=disable TimeZone=Asia/Shanghai"
|
||||||
sqlserverDSN = "sqlserver://sa:LoremIpsum86@localhost:9930?database=master"
|
sqlserverDSN = "sqlserver://sa:LoremIpsum86@localhost:9930?database=master"
|
||||||
tidbDSN = "root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local"
|
tidbDSN = "root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local"
|
||||||
)
|
)
|
||||||
@ -65,6 +67,15 @@ func OpenTestConnection(cfg *gorm.Config) (db *gorm.DB, err error) {
|
|||||||
DSN: dbDSN,
|
DSN: dbDSN,
|
||||||
PreferSimpleProtocol: true,
|
PreferSimpleProtocol: true,
|
||||||
}), cfg)
|
}), cfg)
|
||||||
|
case "gaussdb":
|
||||||
|
log.Println("testing gaussdb...")
|
||||||
|
if dbDSN == "" {
|
||||||
|
dbDSN = gaussdbDSN
|
||||||
|
}
|
||||||
|
db, err = gorm.Open(gaussdb.New(gaussdb.Config{
|
||||||
|
DSN: dbDSN,
|
||||||
|
PreferSimpleProtocol: true,
|
||||||
|
}), cfg)
|
||||||
case "sqlserver":
|
case "sqlserver":
|
||||||
// go install github.com/microsoft/go-sqlcmd/cmd/sqlcmd@latest
|
// go install github.com/microsoft/go-sqlcmd/cmd/sqlcmd@latest
|
||||||
// SQLCMDPASSWORD=LoremIpsum86 sqlcmd -U sa -S localhost:9930
|
// SQLCMDPASSWORD=LoremIpsum86 sqlcmd -U sa -S localhost:9930
|
||||||
|
@ -765,9 +765,9 @@ func TestSaveWithPrimaryValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only sqlite, postgres, sqlserver support returning
|
// only sqlite, postgres, gaussdb, sqlserver support returning
|
||||||
func TestUpdateReturning(t *testing.T) {
|
func TestUpdateReturning(t *testing.T) {
|
||||||
if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "sqlserver" {
|
if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" && DB.Dialector.Name() != "sqlserver" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,9 +883,9 @@ func TestSaveWithHooks(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only postgres, sqlserver, sqlite support update from
|
// only postgres, gaussdb, sqlserver, sqlite support update from
|
||||||
func TestUpdateFrom(t *testing.T) {
|
func TestUpdateFrom(t *testing.T) {
|
||||||
if DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "sqlserver" {
|
if DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" && DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "sqlserver" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user