Skip to content

Extract BINARY column size schema details #480 #481

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
41 changes: 40 additions & 1 deletion schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package schema
import (
"database/sql"
"fmt"
"strconv"
"strings"

"github.com/pingcap/errors"
Expand All @@ -23,7 +24,7 @@ const (
TYPE_FLOAT // float, double
TYPE_ENUM // enum
TYPE_SET // set
TYPE_STRING // other
TYPE_STRING // char, varchar, etc.
TYPE_DATETIME // datetime
TYPE_TIMESTAMP // timestamp
TYPE_DATE // date
Expand All @@ -32,6 +33,7 @@ const (
TYPE_JSON // json
TYPE_DECIMAL // decimal
TYPE_MEDIUM_INT
TYPE_BINARY // binary, varbinary
)

type TableColumn struct {
Expand All @@ -43,6 +45,8 @@ type TableColumn struct {
IsUnsigned bool
EnumValues []string
SetValues []string
FixedSize uint
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see mostly FixedSize = MaxSize, can we just use one size?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MaxSize is literally the maximum amount of data (e.g., characters in a varchar) that you can store. For example, for a varchar(40) it is 40

FixedSize, on the other hand, is the number of characters that are stored by mysql - for example for a char(40) it is 40.

In an earlier revision, I just had a Size property, but that does not help in my case: I also need to have a flag that indicates whether that size is variable or fixed.

Thus, since I did not want to limit how this property can be used, I decided against a boolean flag of what the size means and simply extract the size in both ways, although only 1 applies (similar to how we have EnumValues versus SetValues)

MaxSize uint
}

type Index struct {
Expand Down Expand Up @@ -94,6 +98,14 @@ func (ta *Table) AddColumn(name string, columnType string, collation string, ext
")"),
"'", "", -1),
",")
} else if strings.HasPrefix(columnType, "binary") {
ta.Columns[index].Type = TYPE_BINARY
size := getSizeFromColumnType(columnType)
ta.Columns[index].MaxSize = size
ta.Columns[index].FixedSize = size
} else if strings.HasPrefix(columnType, "varbinary") {
ta.Columns[index].Type = TYPE_BINARY
ta.Columns[index].MaxSize = getSizeFromColumnType(columnType)
} else if strings.HasPrefix(columnType, "datetime") {
ta.Columns[index].Type = TYPE_DATETIME
} else if strings.HasPrefix(columnType, "timestamp") {
Expand All @@ -110,8 +122,14 @@ func (ta *Table) AddColumn(name string, columnType string, collation string, ext
ta.Columns[index].Type = TYPE_MEDIUM_INT
} else if strings.Contains(columnType, "int") || strings.HasPrefix(columnType, "year") {
ta.Columns[index].Type = TYPE_NUMBER
} else if strings.HasPrefix(columnType, "char") {
ta.Columns[index].Type = TYPE_STRING
size := getSizeFromColumnType(columnType)
ta.Columns[index].FixedSize = size
ta.Columns[index].MaxSize = size
} else {
ta.Columns[index].Type = TYPE_STRING
ta.Columns[index].MaxSize = getSizeFromColumnType(columnType)
}

if strings.Contains(columnType, "unsigned") || strings.Contains(columnType, "zerofill") {
Expand All @@ -124,6 +142,27 @@ func (ta *Table) AddColumn(name string, columnType string, collation string, ext
}
}

func getSizeFromColumnType(columnType string) uint {
startIndex := strings.Index(columnType, "(")
if startIndex < 0 {
return 0
}

// we are searching for the first () and there may not be any closing
// brackets before the opening, so no need search at the offset from the
// opening ones
endIndex := strings.Index(columnType, ")")
if startIndex < 0 || endIndex < 0 || startIndex > endIndex {
return 0
}

i, err := strconv.Atoi(columnType[startIndex+1:endIndex])
if err != nil || i < 0 {
return 0
}
return uint(i)
}

func (ta *Table) FindColumn(name string) int {
for i, col := range ta.Columns {
if col.Name == name {
Expand Down
19 changes: 18 additions & 1 deletion schema/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ func (s *schemaTestSuite) TestSchema(c *C) {
zfint INT ZEROFILL,
name_ucs VARCHAR(256) CHARACTER SET ucs2,
name_utf8 VARCHAR(256) CHARACTER SET utf8,
name_char CHAR(10),
name_binary BINARY(11),
name_varbinary VARBINARY(12),
PRIMARY KEY(id2, id),
UNIQUE (id1),
INDEX name_idx (name)
Expand All @@ -74,20 +77,34 @@ func (s *schemaTestSuite) TestSchema(c *C) {
ta, err := NewTable(s.conn, "test", "schema_test")
c.Assert(err, IsNil)

c.Assert(ta.Columns, HasLen, 12)
c.Assert(ta.Columns, HasLen, 15)
c.Assert(ta.Indexes, HasLen, 3)
c.Assert(ta.PKColumns, DeepEquals, []int{2, 0})
c.Assert(ta.Indexes[0].Columns, HasLen, 2)
c.Assert(ta.Indexes[0].Name, Equals, "PRIMARY")
c.Assert(ta.Indexes[2].Name, Equals, "name_idx")
c.Assert(ta.Columns[3].Type, Equals, TYPE_STRING)
c.Assert(ta.Columns[3].MaxSize, Equals, uint(256))
c.Assert(ta.Columns[3].FixedSize, Equals, uint(0))
c.Assert(ta.Columns[4].EnumValues, DeepEquals, []string{"appointing", "serving", "abnormal", "stop", "noaftermarket", "finish", "financial_audit"})
c.Assert(ta.Columns[5].SetValues, DeepEquals, []string{"a", "b", "c"})
c.Assert(ta.Columns[7].Type, Equals, TYPE_DECIMAL)
c.Assert(ta.Columns[0].IsUnsigned, IsFalse)
c.Assert(ta.Columns[8].IsUnsigned, IsTrue)
c.Assert(ta.Columns[9].IsUnsigned, IsTrue)
c.Assert(ta.Columns[10].Collation, Matches, "^ucs2.*")
c.Assert(ta.Columns[10].MaxSize, Equals, uint(256))
c.Assert(ta.Columns[10].FixedSize, Equals, uint(0))
c.Assert(ta.Columns[11].Collation, Matches, "^utf8.*")
c.Assert(ta.Columns[12].Type, Equals, TYPE_STRING)
c.Assert(ta.Columns[12].MaxSize, Equals, uint(10))
c.Assert(ta.Columns[12].FixedSize, Equals, uint(10))
c.Assert(ta.Columns[13].Type, Equals, TYPE_BINARY)
c.Assert(ta.Columns[13].MaxSize, Equals, uint(11))
c.Assert(ta.Columns[13].FixedSize, Equals, uint(11))
c.Assert(ta.Columns[14].Type, Equals, TYPE_BINARY)
c.Assert(ta.Columns[14].MaxSize, Equals, uint(12))
c.Assert(ta.Columns[14].FixedSize, Equals, uint(0))

taSqlDb, err := NewTableFromSqlDB(s.sqlDB, "test", "schema_test")
c.Assert(err, IsNil)
Expand Down