Skip to content
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

Added the backend changes for check constraints #7

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions internal/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ const (
SequenceCreated
ForeignKeyActionNotSupported
NumericPKNotSupported
TypeMismatch
)

const (
Expand Down
7 changes: 6 additions & 1 deletion internal/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (

type Counter struct {
counterMutex sync.Mutex
ObjectId string
ObjectId string
}

var Cntr Counter
Expand Down Expand Up @@ -65,6 +65,11 @@ func GenerateForeignkeyId() string {
func GenerateIndexesId() string {
return GenerateId("i")
}

func GenerateCheckConstrainstId() string {
return GenerateId("ck")
}

func GenerateRuleId() string {
return GenerateId("r")
}
Expand Down
13 changes: 13 additions & 0 deletions internal/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,19 @@ func ToSpannerIndexName(conv *Conv, srcIndexName string) string {
return getSpannerValidName(conv, srcIndexName)
}

// Note that the check constraints names in spanner have to be globally unique
// (across the database). But in some source databases, such as MySQL,
// they only have to be unique for a table. Hence we must map each source
// constraint name to a unique spanner constraint name.
func ToSpannerCheckConstraintName(conv *Conv, srcCheckConstraintName string) string {
return getSpannerValidName(conv, srcCheckConstraintName)
}

func GetSpannerValidExpression(cks []ddl.CheckConstraint) []ddl.CheckConstraint {
// TODO validate the check constraints data with batch verification then send back
return cks
}

// conv.UsedNames tracks Spanner names that have been used for table names, foreign key constraints
// and indexes. We use this to ensure we generate unique names when
// we map from source dbs to Spanner since Spanner requires all these names to be
Expand Down
7 changes: 7 additions & 0 deletions internal/reports/report_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,13 @@ func buildTableReportBody(conv *internal.Conv, tableId string, issues map[string
Description: fmt.Sprintf("UNIQUE constraint on column(s) '%s' replaced with primary key since table '%s' didn't have one. Spanner requires a primary key for every table", strings.Join(uniquePK, ", "), conv.SpSchema[tableId].Name),
}
l = append(l, toAppend)
case internal.TypeMismatch:
toAppend := Issue{
Category: IssueDB[i].Category,
Description: fmt.Sprintf("Table '%s': Type mismatch in '%s'column affecting check constraints. Verify data type compatibility with constraint logic", conv.SpSchema[tableId].Name, conv.SpSchema[tableId].ColDefs[colId].Name),
}
l = append(l, toAppend)

default:
toAppend := Issue{
Category: IssueDB[i].Category,
Expand Down
38 changes: 23 additions & 15 deletions schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,27 @@ import (

// 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
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
CheckConstraints []CheckConstraint
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
AutoGen ddl.AutoGenCol
Name string
Type Type
NotNull bool
Ignored Ignored
Id string
AutoGen ddl.AutoGenCol
}

// ForeignKey represents a foreign key.
Expand All @@ -76,6 +77,13 @@ type ForeignKey struct {
Id string
}

// CheckConstraints represents a check constraint defined in the schema.
type CheckConstraint struct {
Name string
Expr string
Id string
}

// Key respresents a primary key or index key.
type Key struct {
ColId string
Expand Down
23 changes: 12 additions & 11 deletions sources/common/infoschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type InfoSchema interface {
GetColumns(conv *internal.Conv, table SchemaAndName, constraints map[string][]string, primaryKeys []string) (map[string]schema.Column, []string, error)
GetRowsFromTable(conv *internal.Conv, srcTable string) (interface{}, error)
GetRowCount(table SchemaAndName) (int64, error)
GetConstraints(conv *internal.Conv, table SchemaAndName) ([]string, map[string][]string, error)
GetConstraints(conv *internal.Conv, table SchemaAndName) ([]string, []schema.CheckConstraint, map[string][]string, error)
GetForeignKeys(conv *internal.Conv, table SchemaAndName) (foreignKeys []schema.ForeignKey, err error)
GetIndexes(conv *internal.Conv, table SchemaAndName, colNameIdMp map[string]string) ([]schema.Index, error)
ProcessData(conv *internal.Conv, tableId string, srcSchema schema.Table, spCols []string, spSchema ddl.CreateTable, additionalAttributes internal.AdditionalDataAttributes) error
Expand Down Expand Up @@ -185,7 +185,7 @@ func (is *InfoSchemaImpl) processTable(conv *internal.Conv, table SchemaAndName,
var t schema.Table
fmt.Println("processing schema for table", table)
tblId := internal.GenerateTableId()
primaryKeys, constraints, err := infoSchema.GetConstraints(conv, table)
primaryKeys, checkConstraints, constraints, err := infoSchema.GetConstraints(conv, table)
if err != nil {
return t, fmt.Errorf("couldn't get constraints for table %s.%s: %s", table.Schema, table.Name, err)
}
Expand Down Expand Up @@ -215,15 +215,16 @@ func (is *InfoSchemaImpl) processTable(conv *internal.Conv, table SchemaAndName,
schemaPKeys = append(schemaPKeys, schema.Key{ColId: colNameIdMap[k]})
}
t = schema.Table{
Id: tblId,
Name: name,
Schema: table.Schema,
ColIds: colIds,
ColNameIdMap: colNameIdMap,
ColDefs: colDefs,
PrimaryKeys: schemaPKeys,
Indexes: indexes,
ForeignKeys: foreignKeys}
Id: tblId,
Name: name,
Schema: table.Schema,
ColIds: colIds,
ColNameIdMap: colNameIdMap,
ColDefs: colDefs,
PrimaryKeys: schemaPKeys,
CheckConstraints: checkConstraints,
Indexes: indexes,
ForeignKeys: foreignKeys}
return t, nil
}

Expand Down
32 changes: 24 additions & 8 deletions sources/common/toddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,15 @@ func (ss *SchemaToSpannerImpl) SchemaToSpannerDDLHelper(conv *internal.Conv, tod
}
comment := "Spanner schema for source table " + quoteIfNeeded(srcTable.Name)
conv.SpSchema[srcTable.Id] = ddl.CreateTable{
Name: spTableName,
ColIds: spColIds,
ColDefs: spColDef,
PrimaryKeys: cvtPrimaryKeys(srcTable.PrimaryKeys),
ForeignKeys: cvtForeignKeys(conv, spTableName, srcTable.Id, srcTable.ForeignKeys, isRestore),
Indexes: cvtIndexes(conv, srcTable.Id, srcTable.Indexes, spColIds, spColDef),
Comment: comment,
Id: srcTable.Id}
Name: spTableName,
ColIds: spColIds,
ColDefs: spColDef,
PrimaryKeys: cvtPrimaryKeys(srcTable.PrimaryKeys),
ForeignKeys: cvtForeignKeys(conv, spTableName, srcTable.Id, srcTable.ForeignKeys, isRestore),
CheckConstraints: cvtCheckConstraint(conv, srcTable.CheckConstraints),
Indexes: cvtIndexes(conv, srcTable.Id, srcTable.Indexes, spColIds, spColDef),
Comment: comment,
Id: srcTable.Id}
return nil
}

Expand Down Expand Up @@ -234,6 +235,21 @@ func cvtForeignKeys(conv *internal.Conv, spTableName string, srcTableId string,
return spKeys
}

func cvtCheckConstraint(conv *internal.Conv, srcKeys []schema.CheckConstraint) []ddl.CheckConstraint {
var spcks []ddl.CheckConstraint

for _, cks := range srcKeys {
spcks = append(spcks, ddl.CheckConstraint{
Id: cks.Id,
Name: internal.ToSpannerCheckConstraintName(conv, cks.Name),
Expr: cks.Expr,
})

}

return internal.GetSpannerValidExpression(spcks)
}

func CvtForeignKeysHelper(conv *internal.Conv, spTableName string, srcTableId string, srcKey schema.ForeignKey, isRestore bool) (ddl.Foreignkey, error) {
if len(srcKey.ColIds) != len(srcKey.ReferColumnIds) {
conv.Unexpected(fmt.Sprintf("ConvertForeignKeys: ColIds and referColumns don't have the same lengths: len(columns)=%d, len(referColumns)=%d for source tableId: %s, referenced table: %s", len(srcKey.ColIds), len(srcKey.ReferColumnIds), srcTableId, srcKey.ReferTableId))
Expand Down
31 changes: 31 additions & 0 deletions sources/common/toddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,3 +428,34 @@ func Test_SchemaToSpannerSequenceHelper(t *testing.T) {
assert.Equal(t, expectedConv, conv)
}
}

func Test_cvtCheckContraint(t *testing.T) {

conv := internal.MakeConv()
srcSchema := []schema.CheckConstraint{
{
Id: "ck1",
Name: "check_1",
Expr: "age > 0",
},
{
Id: "ck1",
Name: "check_2",
Expr: "age < 99",
},
}
spSchema := []ddl.CheckConstraint{
{
Id: "ck1",
Name: "check_1",
Expr: "age > 0",
},
{
Id: "ck1",
Name: "check_2",
Expr: "age < 99",
},
}
result := cvtCheckConstraint(conv, srcSchema)
assert.Equal(t, spSchema, result)
}
6 changes: 3 additions & 3 deletions sources/dynamodb/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,20 @@ func (isi InfoSchemaImpl) GetRowCount(table common.SchemaAndName) (int64, error)
return *result.Table.ItemCount, err
}

func (isi InfoSchemaImpl) GetConstraints(conv *internal.Conv, table common.SchemaAndName) (primaryKeys []string, constraints map[string][]string, err error) {
func (isi InfoSchemaImpl) GetConstraints(conv *internal.Conv, table common.SchemaAndName) (primaryKeys []string, checkConstraints []schema.CheckConstraint, constraints map[string][]string, err error) {
input := &dynamodb.DescribeTableInput{
TableName: aws.String(table.Name),
}
result, err := isi.DynamoClient.DescribeTable(input)
if err != nil {
return primaryKeys, constraints, fmt.Errorf("failed to make a DescribeTable API call for table %v: %v", table.Name, err)
return primaryKeys, checkConstraints, constraints, fmt.Errorf("failed to make a DescribeTable API call for table %v: %v", table.Name, err)
}

// Primary keys.
for _, i := range result.Table.KeySchema {
primaryKeys = append(primaryKeys, *i.AttributeName)
}
return primaryKeys, constraints, nil
return primaryKeys, checkConstraints, constraints, nil
}

func (isi InfoSchemaImpl) GetForeignKeys(conv *internal.Conv, table common.SchemaAndName) (foreignKeys []schema.ForeignKey, err error) {
Expand Down
4 changes: 2 additions & 2 deletions sources/dynamodb/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ func TestInfoSchemaImpl_GetConstraints(t *testing.T) {
dySchema := common.SchemaAndName{Name: "test"}
conv := internal.MakeConv()
isi := InfoSchemaImpl{client, nil, 10}
primaryKeys, constraints, err := isi.GetConstraints(conv, dySchema)
primaryKeys, _, constraints, err := isi.GetConstraints(conv, dySchema)
assert.Nil(t, err)

pKeys := []string{"a", "b"}
Expand Down Expand Up @@ -705,7 +705,7 @@ func TestInfoSchemaImpl_GetColumns(t *testing.T) {
client := &mockDynamoClient{
scanOutputs: scanOutputs,
}
dySchema := common.SchemaAndName{Name: "test", Id: "t1"}
dySchema := common.SchemaAndName{Name: "test", Id: "t1"}

isi := InfoSchemaImpl{client, nil, 10}

Expand Down
Loading
Loading