-
Notifications
You must be signed in to change notification settings - Fork 56
/
schema.go
152 lines (141 loc) · 4.95 KB
/
schema.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package schema provides a generic representation of database
// schemas. Note that our goal is not to faithfully represent all
// aspects of the schema, but just the relevant components for
// conversion to Spanner and reporting on the quality of the
// conversion (this motivates us to keep partial information about
// some features we will report on but not use in the conversion
// e.g. default values, check constraints).
//
// The current version supports PostgreSQL. Expect it to grow as we
// support other databases. We might eventually support the Spanner
// schema, and potentially get rid of the ddl package.
package schema
import (
"fmt"
"strconv"
"strings"
)
// Table represents a database table.
type Table struct {
Name string
Schema string
ColIds []string // List of column Ids (for predictable iteration order e.g. printing).
ColDefs map[string]Column // Details of columns.
ColNameIdMap map[string]string `json:"-"` // Computed every time just after conv is generated or after any column renaming
PrimaryKeys []Key
ForeignKeys []ForeignKey
Indexes []Index
Id string
}
// Column represents a database column.
// TODO: add support for foreign keys.
type Column struct {
Name string
Type Type
NotNull bool
Ignored Ignored
Id string
}
// ForeignKey represents a foreign key.
// Note that the fields onDelete and onUpdate describe actions
// for when keys are deleted or updated. Different source databases
// support different actions. For example, mysql supports RESTRICT,
// CASCADE, SET NULL, NO ACTION, and SET DEFAULT
// (see https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html).
type ForeignKey struct {
Name string
ColIds []string
ColumnNames []string `json:"-"`
ReferTableId string
ReferTableName string `json:"-"`
ReferColumnIds []string // len(ReferColumnIds) must be same as len(ColIds)
ReferColumnNames []string `json:"-"`
OnDelete string
OnUpdate string
Id string
}
// Key respresents a primary key or index key.
type Key struct {
ColId string
Desc bool // By default, order is ASC. Set to true to specifiy DESC.
Order int
}
// Index represents a database index.
// Index represents a database index.
// The only way we represent unique constraints is via indexes. All source database
// unique constraints will be transformed into this representation, including:
// i) A column level constraint (as part of a CREATE TABLE statement)
// ii) A table level constraint (as part of a CREATE TABLE statement)
// iii) An index (as part of a CREATE TABLE statement)
// iv) Added via an ALTER TABLE constraint (changing column constraints, table constraints or index definitions)
// v) Added via a CREATE UNIQUE INDEX statement (which internally maps to an alter table statement).
// We use this single representation of unique constraints to simplify their processing and avoid having
// to handle lots of cases for the same concept. Our choice of an index representation for unique is largely
// motivated by the fact that databases typically implement UNIQUE via an index.
type Index struct {
Name string
Unique bool
Keys []Key
Id string
StoredColumnIds []string
}
// Type represents the type of a column.
type Type struct {
Name string
Mods []int64 // List of modifiers (aka type parameters e.g. varchar(8) or numeric(6, 4).
ArrayBounds []int64 // Empty for scalar types.
}
// Ignored represents column properties/constraints that are not
// represented. We drop the details, but retain presence/absence for
// reporting purposes.
type Ignored struct {
Check bool
Identity bool
Default bool
Exclusion bool
ForeignKey bool
AutoIncrement bool
}
// Print converts ty to a string suitable for printing.
func (ty Type) Print() string {
s := ty.Name
if len(ty.Mods) > 0 {
var l []string
for _, x := range ty.Mods {
l = append(l, strconv.FormatInt(x, 10))
}
s = fmt.Sprintf("%s(%s)", s, strings.Join(l, ","))
}
if len(ty.ArrayBounds) > 0 {
l := []string{s}
for _, x := range ty.ArrayBounds {
if x == -1 {
l = append(l, "[]")
} else {
l = append(l, fmt.Sprintf("[%d]", x))
}
}
s = strings.Join(l, "")
}
return s
}
func MakeType() Type {
return Type{
Name: "",
Mods: []int64{},
ArrayBounds: []int64{},
}
}