Skip to content
This repository has been archived by the owner on Sep 7, 2021. It is now read-only.
This repository is currently being migrated. It's locked while the migration is in progress.

Fix default value parse bugs #1437

Merged
merged 6 commits into from
Sep 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 7 additions & 12 deletions dialect_mssql.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ func (db *mssql) TableCheckSql(tableName string) (string, []interface{}) {
func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
args := []interface{}{}
s := `select a.name as name, b.name as ctype,a.max_length,a.precision,a.scale,a.is_nullable as nullable,
"default_is_null" = (CASE WHEN c.text is null THEN 1 ELSE 0 END),
replace(replace(isnull(c.text,''),'(',''),')','') as vdefault,
ISNULL(i.is_primary_key, 0)
from sys.columns a
Expand All @@ -361,8 +362,8 @@ func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column
for rows.Next() {
var name, ctype, vdefault string
var maxLen, precision, scale int
var nullable, isPK bool
err = rows.Scan(&name, &ctype, &maxLen, &precision, &scale, &nullable, &vdefault, &isPK)
var nullable, isPK, defaultIsNull bool
err = rows.Scan(&name, &ctype, &maxLen, &precision, &scale, &nullable, &defaultIsNull, &vdefault, &isPK)
if err != nil {
return nil, nil, err
}
Expand All @@ -371,7 +372,10 @@ func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column
col.Indexes = make(map[string]int)
col.Name = strings.Trim(name, "` ")
col.Nullable = nullable
col.Default = vdefault
col.DefaultIsEmpty = defaultIsNull
if !defaultIsNull {
col.Default = vdefault
}
col.IsPrimaryKey = isPK
ct := strings.ToUpper(ctype)
if ct == "DECIMAL" {
Expand All @@ -395,15 +399,6 @@ func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column
}
}

if col.SQLType.IsText() || col.SQLType.IsTime() {
if col.Default != "" {
col.Default = "'" + col.Default + "'"
} else {
if col.DefaultIsEmpty {
col.Default = "''"
}
}
}
cols[col.Name] = col
colSeq = append(colSeq, col.Name)
}
Expand Down
16 changes: 7 additions & 9 deletions dialect_mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,9 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column

if colDefault != nil {
col.Default = *colDefault
if col.Default == "" {
col.DefaultIsEmpty = true
}
col.DefaultIsEmpty = false
} else {
col.DefaultIsEmpty = true
}

cts := strings.Split(colType, "(")
Expand Down Expand Up @@ -411,13 +411,11 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column
col.IsAutoIncrement = true
}

if col.SQLType.IsText() || col.SQLType.IsTime() {
if col.Default != "" {
if !col.DefaultIsEmpty {
if col.SQLType.IsText() {
col.Default = "'" + col.Default + "'"
} else if col.SQLType.IsTime() && col.Default != "CURRENT_TIMESTAMP" {
col.Default = "'" + col.Default + "'"
} else {
if col.DefaultIsEmpty {
col.Default = "''"
}
}
}
cols[col.Name] = col
Expand Down
32 changes: 19 additions & 13 deletions dialect_postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -1005,16 +1005,18 @@ WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.att

col.Name = strings.Trim(colName, `" `)

if colDefault != nil || isPK {
if isPK {
col.IsPrimaryKey = true
} else {
col.Default = *colDefault
if colDefault != nil {
col.Default = *colDefault
col.DefaultIsEmpty = false
if strings.HasPrefix(col.Default, "nextval(") {
col.IsAutoIncrement = true
}
} else {
col.DefaultIsEmpty = true
}

if colDefault != nil && strings.HasPrefix(*colDefault, "nextval(") {
col.IsAutoIncrement = true
if isPK {
col.IsPrimaryKey = true
}

col.Nullable = (isNullable == "YES")
Expand Down Expand Up @@ -1043,12 +1045,16 @@ WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.att

col.Length = maxLen

if col.SQLType.IsText() || col.SQLType.IsTime() {
if col.Default != "" {
col.Default = "'" + col.Default + "'"
} else {
if col.DefaultIsEmpty {
col.Default = "''"
if !col.DefaultIsEmpty {
if col.SQLType.IsText() {
if strings.HasSuffix(col.Default, "::character varying") {
col.Default = strings.TrimRight(col.Default, "::character varying")
} else if !strings.HasPrefix(col.Default, "'") {
col.Default = "'" + col.Default + "'"
}
} else if col.SQLType.IsTime() {
if strings.HasSuffix(col.Default, "::timestamp without time zone") {
col.Default = strings.TrimRight(col.Default, "::timestamp without time zone")
}
}
}
Expand Down
33 changes: 29 additions & 4 deletions dialect_sqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,34 @@ func (db *sqlite3) IsColumnExist(tableName, colName string) (bool, error) {
return false, nil
}

// splitColStr splits a sqlite col strings as fields
func splitColStr(colStr string) []string {
colStr = strings.TrimSpace(colStr)
var results = make([]string, 0, 10)
var lastIdx int
var hasC, hasQuote bool
for i, c := range colStr {
if c == ' ' && !hasQuote {
if hasC {
results = append(results, colStr[lastIdx:i])
hasC = false
}
} else {
if c == '\'' {
hasQuote = !hasQuote
}
if !hasC {
lastIdx = i
}
hasC = true
if i == len(colStr)-1 {
results = append(results, colStr[lastIdx:i+1])
}
}
}
return results
}

func (db *sqlite3) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
args := []interface{}{tableName}
s := "SELECT sql FROM sqlite_master WHERE type='table' and name = ?"
Expand Down Expand Up @@ -315,7 +343,7 @@ func (db *sqlite3) GetColumns(tableName string) ([]string, map[string]*core.Colu
continue
}

fields := strings.Fields(strings.TrimSpace(colStr))
fields := splitColStr(colStr)
col := new(core.Column)
col.Indexes = make(map[string]int)
col.Nullable = true
Expand Down Expand Up @@ -344,9 +372,6 @@ func (db *sqlite3) GetColumns(tableName string) ([]string, map[string]*core.Colu
col.DefaultIsEmpty = false
}
}
if !col.SQLType.IsNumeric() && !col.DefaultIsEmpty {
col.Default = "'" + col.Default + "'"
}
cols[col.Name] = col
colSeq = append(colSeq, col.Name)
}
Expand Down
35 changes: 35 additions & 0 deletions dialect_sqlite3_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package xorm

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestSplitColStr(t *testing.T) {
var kases = []struct {
colStr string
fields []string
}{
{
colStr: "`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
fields: []string{
"`id`", "INTEGER", "PRIMARY", "KEY", "AUTOINCREMENT", "NOT", "NULL",
},
},
{
colStr: "`created` DATETIME DEFAULT '2006-01-02 15:04:05' NULL",
fields: []string{
"`created`", "DATETIME", "DEFAULT", "'2006-01-02 15:04:05'", "NULL",
},
},
}

for _, kase := range kases {
assert.EqualValues(t, kase.fields, splitColStr(kase.colStr))
}
}
11 changes: 9 additions & 2 deletions engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -907,8 +907,15 @@ func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
fieldType := fieldValue.Type()

if ormTagStr != "" {
col = &core.Column{FieldName: t.Field(i).Name, Nullable: true, IsPrimaryKey: false,
IsAutoIncrement: false, MapType: core.TWOSIDES, Indexes: make(map[string]int)}
col = &core.Column{
FieldName: t.Field(i).Name,
Nullable: true,
IsPrimaryKey: false,
IsAutoIncrement: false,
MapType: core.TWOSIDES,
Indexes: make(map[string]int),
DefaultIsEmpty: true,
}
tags := splitTag(ormTagStr)

if len(tags) > 0 {
Expand Down
19 changes: 0 additions & 19 deletions helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,6 @@ import (
"github.com/stretchr/testify/assert"
)

func TestSplitTag(t *testing.T) {
var cases = []struct {
tag string
tags []string
}{
{"not null default '2000-01-01 00:00:00' TIMESTAMP", []string{"not", "null", "default", "'2000-01-01 00:00:00'", "TIMESTAMP"}},
{"TEXT", []string{"TEXT"}},
{"default('2000-01-01 00:00:00')", []string{"default('2000-01-01 00:00:00')"}},
{"json binary", []string{"json", "binary"}},
}

for _, kase := range cases {
tags := splitTag(kase.tag)
if !sliceEq(tags, kase.tags) {
t.Fatalf("[%d]%v is not equal [%d]%v", len(tags), tags, len(kase.tags), kase.tags)
}
}
}

func TestEraseAny(t *testing.T) {
raw := "SELECT * FROM `table`.[table_name]"
assert.EqualValues(t, raw, eraseAny(raw))
Expand Down
1 change: 1 addition & 0 deletions tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func DefaultTagHandler(ctx *tagContext) error {
ctx.col.Default = ctx.nextTag
ctx.ignoreNext = true
}
ctx.col.DefaultIsEmpty = false
return nil
}

Expand Down
Loading