Skip to content

Commit e64be9f

Browse files
committed
add schema
1 parent c6896ff commit e64be9f

File tree

3 files changed

+244
-0
lines changed

3 files changed

+244
-0
lines changed

schema/schema.go

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// Copyright 2012, Google Inc. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package schema
6+
7+
import (
8+
"fmt"
9+
"github.com/siddontang/go-mysql/client"
10+
)
11+
12+
type TableColumn struct {
13+
Name string
14+
Type string
15+
IsAuto bool
16+
}
17+
18+
type Index struct {
19+
Name string
20+
Columns []string
21+
Cardinality []uint64
22+
}
23+
24+
type Table struct {
25+
Schema string
26+
Name string
27+
28+
Columns []TableColumn
29+
Indexes []*Index
30+
PKColumns []int
31+
}
32+
33+
func (ta *Table) AddColumn(name string, columnType string, extra string) {
34+
index := len(ta.Columns)
35+
ta.Columns = append(ta.Columns, TableColumn{Name: name})
36+
37+
ta.Columns[index].Type = columnType
38+
if extra == "auto_increment" {
39+
ta.Columns[index].IsAuto = true
40+
}
41+
}
42+
43+
func (ta *Table) FindColumn(name string) int {
44+
for i, col := range ta.Columns {
45+
if col.Name == name {
46+
return i
47+
}
48+
}
49+
return -1
50+
}
51+
52+
func (ta *Table) GetPKColumn(index int) *TableColumn {
53+
return &ta.Columns[ta.PKColumns[index]]
54+
}
55+
56+
func (ta *Table) AddIndex(name string) (index *Index) {
57+
index = NewIndex(name)
58+
ta.Indexes = append(ta.Indexes, index)
59+
return index
60+
}
61+
62+
func NewIndex(name string) *Index {
63+
return &Index{name, make([]string, 0, 8), make([]uint64, 0, 8)}
64+
}
65+
66+
func (idx *Index) AddColumn(name string, cardinality uint64) {
67+
idx.Columns = append(idx.Columns, name)
68+
if cardinality == 0 {
69+
cardinality = uint64(len(idx.Cardinality) + 1)
70+
}
71+
idx.Cardinality = append(idx.Cardinality, cardinality)
72+
}
73+
74+
func (idx *Index) FindColumn(name string) int {
75+
for i, colName := range idx.Columns {
76+
if name == colName {
77+
return i
78+
}
79+
}
80+
return -1
81+
}
82+
83+
func NewTable(conn *client.Conn, schema string, name string) (*Table, error) {
84+
ta := &Table{
85+
Schema: schema,
86+
Name: name,
87+
Columns: make([]TableColumn, 0, 16),
88+
Indexes: make([]*Index, 0, 8),
89+
}
90+
91+
if err := ta.fetchColumns(conn); err != nil {
92+
return nil, err
93+
}
94+
95+
if err := ta.fetchIndexes(conn); err != nil {
96+
return nil, err
97+
}
98+
99+
return ta, nil
100+
}
101+
102+
func (ta *Table) fetchColumns(conn *client.Conn) error {
103+
r, err := conn.Execute(fmt.Sprintf("describe %s.%s", ta.Schema, ta.Name))
104+
if err != nil {
105+
return err
106+
}
107+
108+
for i := 0; i < r.RowNumber(); i++ {
109+
name, _ := r.GetString(i, 0)
110+
colType, _ := r.GetString(i, 1)
111+
extra, _ := r.GetString(i, 5)
112+
113+
ta.AddColumn(name, colType, extra)
114+
}
115+
116+
return nil
117+
}
118+
119+
func (ta *Table) fetchIndexes(conn *client.Conn) error {
120+
r, err := conn.Execute(fmt.Sprintf("show index from %s.%s", ta.Schema, ta.Name))
121+
if err != nil {
122+
return err
123+
}
124+
var currentIndex *Index
125+
currentName := ""
126+
127+
for i := 0; i < r.RowNumber(); i++ {
128+
indexName, _ := r.GetString(i, 2)
129+
if currentName != indexName {
130+
currentIndex = ta.AddIndex(indexName)
131+
currentName = indexName
132+
}
133+
cardinality, _ := r.GetUint(i, 6)
134+
colName, _ := r.GetString(i, 4)
135+
currentIndex.AddColumn(colName, cardinality)
136+
}
137+
138+
if len(ta.Indexes) == 0 {
139+
return nil
140+
}
141+
142+
pkIndex := ta.Indexes[0]
143+
if pkIndex.Name != "PRIMARY" {
144+
return nil
145+
}
146+
147+
ta.PKColumns = make([]int, len(pkIndex.Columns))
148+
for i, pkCol := range pkIndex.Columns {
149+
ta.PKColumns[i] = ta.FindColumn(pkCol)
150+
}
151+
152+
return nil
153+
}

schema/schema_test.go

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package schema
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"github.com/siddontang/go-mysql/client"
7+
. "gopkg.in/check.v1"
8+
"testing"
9+
)
10+
11+
// use docker mysql for test
12+
var host = flag.String("host", "127.0.0.1", "MySQL host")
13+
14+
func Test(t *testing.T) {
15+
TestingT(t)
16+
}
17+
18+
type schemaTestSuite struct {
19+
conn *client.Conn
20+
}
21+
22+
var _ = Suite(&schemaTestSuite{})
23+
24+
func (s *schemaTestSuite) SetUpSuite(c *C) {
25+
var err error
26+
s.conn, err = client.Connect(fmt.Sprintf("%s:%d", *host, 3306), "root", "", "test")
27+
c.Assert(err, IsNil)
28+
}
29+
30+
func (s *schemaTestSuite) TearDownSuite(c *C) {
31+
if s.conn != nil {
32+
s.conn.Close()
33+
}
34+
}
35+
36+
func (s *schemaTestSuite) TestSchema(c *C) {
37+
str := `
38+
CREATE TABLE IF NOT EXISTS schema_test (
39+
id INT,
40+
id1 INT,
41+
id2 INT,
42+
name VARCHAR(256),
43+
e ENUM("a", "b", "c"),
44+
f FLOAT,
45+
PRIMARY KEY(id2, id),
46+
UNIQUE (id1),
47+
INDEX name_idx (name)
48+
) ENGINE = INNODB;
49+
`
50+
51+
_, err := s.conn.Execute(str)
52+
c.Assert(err, IsNil)
53+
54+
ta, err := NewTable(s.conn, "test", "schema_test")
55+
c.Assert(err, IsNil)
56+
57+
c.Assert(ta.Columns, HasLen, 6)
58+
c.Assert(ta.Indexes, HasLen, 3)
59+
c.Assert(ta.PKColumns, DeepEquals, []int{2, 0})
60+
c.Assert(ta.Indexes[0].Columns, HasLen, 2)
61+
c.Assert(ta.Indexes[0].Name, Equals, "PRIMARY")
62+
c.Assert(ta.Indexes[2].Name, Equals, "name_idx")
63+
}

vitess_license

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Copyright 2012, Google Inc.
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are
6+
met:
7+
8+
* Redistributions of source code must retain the above copyright
9+
notice, this list of conditions and the following disclaimer.
10+
* Redistributions in binary form must reproduce the above
11+
copyright notice, this list of conditions and the following disclaimer
12+
in the documentation and/or other materials provided with the
13+
distribution.
14+
* Neither the name of Google Inc. nor the names of its
15+
contributors may be used to endorse or promote products derived from
16+
this software without specific prior written permission.
17+
18+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

0 commit comments

Comments
 (0)