Skip to content

Commit

Permalink
clickhouse < 22.0's columns doesn't support precision, close #54
Browse files Browse the repository at this point in the history
  • Loading branch information
jinzhu committed Jul 4, 2022
1 parent 214ffb5 commit 44f5337
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 24 deletions.
32 changes: 19 additions & 13 deletions clickhouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,22 @@ import (
)

type Config struct {
DriverName string
DSN string
Conn gorm.ConnPool
DisableDatetimePrecision bool
DontSupportRenameColumn bool
SkipInitializeWithVersion bool
DefaultGranularity int // 1 granule = 8192 rows
DefaultCompression string // default compression algorithm. LZ4 is lossless
DefaultIndexType string // index stores extremes of the expression
DefaultTableEngineOpts string
DriverName string
DSN string
Conn gorm.ConnPool
DisableDatetimePrecision bool
DontSupportRenameColumn bool
DontSupportColumnPrecision bool
SkipInitializeWithVersion bool
DefaultGranularity int // 1 granule = 8192 rows
DefaultCompression string // default compression algorithm. LZ4 is lossless
DefaultIndexType string // index stores extremes of the expression
DefaultTableEngineOpts string
}

type Dialector struct {
*Config
Version string
}

func Open(dsn string) gorm.Dialector {
Expand Down Expand Up @@ -86,17 +88,21 @@ func (dialector Dialector) Initialize(db *gorm.DB) (err error) {
}

if !dialector.SkipInitializeWithVersion {
var vs string
err = db.ConnPool.QueryRowContext(ctx, "SELECT version()").Scan(&vs)
err = db.ConnPool.QueryRowContext(ctx, "SELECT version()").Scan(&dialector.Version)
if err != nil {
return err
}
if dbversion, err := version.NewVersion(vs); err == nil {
if dbversion, err := version.NewVersion(dialector.Version); err == nil {
versionNoRenameColumn, _ := version.NewConstraint("< 20.4")

if versionNoRenameColumn.Check(dbversion) {
dialector.Config.DontSupportRenameColumn = true
}

versionNoPrecisionColumn, _ := version.NewConstraint("< 21.11")
if versionNoPrecisionColumn.Check(dbversion) {
dialector.DontSupportColumnPrecision = true
}
}
}

Expand Down
5 changes: 1 addition & 4 deletions create.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func Create(db *gorm.DB) {
db.Statement.SQL.Grow(180)
db.Statement.AddClauseIfNotExists(clause.Insert{})

if values := callbacks.ConvertToCreateValues(db.Statement); len(values.Values) > 1 {
if values := callbacks.ConvertToCreateValues(db.Statement); len(values.Values) >= 1 {
prepareValues := clause.Values{
Columns: values.Columns,
Values: [][]interface{}{values.Values[0]},
Expand All @@ -38,9 +38,6 @@ func Create(db *gorm.DB) {
}
}
return
} else {
db.Statement.AddClause(values)
db.Statement.Build("INSERT", "VALUES", "ON CONFLICT")
}
}

Expand Down
14 changes: 9 additions & 5 deletions migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

// Errors enumeration
var (
ErrRenameColumnUnsupported = errors.New("renaming column is not supported in your clickhouse version < 20.4.")
ErrRenameColumnUnsupported = errors.New("renaming column is not supported in your clickhouse version < 20.4")
ErrRenameIndexUnsupported = errors.New("renaming index is not supported")
ErrCreateIndexFailed = errors.New("failed to create index with name")
)
Expand Down Expand Up @@ -66,10 +66,7 @@ func (m Migrator) FullDataTypeOf(field *schema.Field) (expr clause.Expr) {
// NOTE: the codec algo name is case sensitive!
if codecstr, ok := field.TagSettings["CODEC"]; ok && codecstr != "" {
// parse codec one by one in the codec option
codecSlice := make([]string, 0, 10)
for _, codec := range strings.Split(codecstr, ",") {
codecSlice = append(codecSlice, codec)
}
codecSlice := strings.Split(codecstr, ",")
codecArgsSQL := m.Dialector.DefaultCompression
if len(codecSlice) > 0 {
codecArgsSQL = strings.Join(codecSlice, ",")
Expand Down Expand Up @@ -302,6 +299,9 @@ func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, error) {
rawColumnTypes, err = rows.ColumnTypes()

columnTypeSQL := "SELECT name, type, default_expression, comment, is_in_primary_key, character_octet_length, numeric_precision, numeric_precision_radix, numeric_scale, datetime_precision FROM system.columns WHERE database = ? AND table = ?"
if m.Dialector.DontSupportColumnPrecision {
columnTypeSQL = "SELECT name, type, default_expression, comment, is_in_primary_key FROM system.columns WHERE database = ? AND table = ?"
}
columns, rowErr := m.DB.Raw(columnTypeSQL, m.CurrentDatabase(), stmt.Table).Rows()
if rowErr != nil {
return rowErr
Expand All @@ -322,6 +322,10 @@ func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, error) {
}
)

if m.Dialector.DontSupportColumnPrecision {
values = []interface{}{&column.NameValue, &column.DataTypeValue, &column.DefaultValueValue, &column.CommentValue, &column.PrimaryKeyValue}
}

if scanErr := columns.Scan(values...); scanErr != nil {
return scanErr
}
Expand Down
4 changes: 2 additions & 2 deletions migrator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ func TestAutoMigrate(t *testing.T) {
t.Fatalf("column name default_value should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
case "debit":
if decimal, scale, ok := columnType.DecimalSize(); !ok || scale != 0 || decimal != 4 {
if decimal, scale, ok := columnType.DecimalSize(); !ok || (scale != 0 || decimal != 4) {
t.Fatalf("column name debit should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
case "birthday":
if decimal, scale, ok := columnType.DecimalSize(); !ok || scale != 0 || decimal != 4 {
if decimal, scale, ok := columnType.DecimalSize(); !ok || (scale != 0 || decimal != 4) {
t.Fatalf("column name birthday should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
}
Expand Down

0 comments on commit 44f5337

Please sign in to comment.