Skip to content

Commit

Permalink
Integration test checkconstraints (GoogleCloudPlatform#983)
Browse files Browse the repository at this point in the history
* verification API and dump flow changes to support MySQL CHECK CONSTRAINTS (GoogleCloudPlatform#978) (#30)

* verification ap and dump flow changes

* fixed IT issue

* Check constraints verificartion api v2 (#24)

* handled function not found

* added unhandled error

* updated the error msg

---------



* fix IT issue

* comment addressed (#27)

* comment addressed
1. rename the functionNotFound
2. added condition to call verification api

* spell checked

---------



* refactor the DbDumpImpl struct (#28)

* refactor the DbDumpImpl struct

* remove the GenerateCheckConstrainstExprId method

---------



* fixed if condition

---------

Co-authored-by: Taher Lakdawala <[email protected]>
Co-authored-by: taherkl <[email protected]>
Co-authored-by: Vivek Yadav <[email protected]>
Co-authored-by: Vivek Yadav <[email protected]>

* added the integration test
1. integration test added for check constraints.

* updated the integration test

* updated the insert query

* removed unwanted code

* fixed minor bug related to dump flow

* resolve the IT issue

* added missing cmd

* fixed the mysql query

* fixed the query
added fixed

* fixed the query (#45)

* fixed the query

* fixed

* fixed the code

* fixed query

* updated the code

* updated the code

---------

Co-authored-by: Vivek Yadav <[email protected]>

* comment addressed (#48)

Co-authored-by: Vivek Yadav <[email protected]>

* added fix (#49)

Co-authored-by: Vivek Yadav <[email protected]>

* fixed the issue without check constraints (#50)

Co-authored-by: Vivek Yadav <[email protected]>

* added the fix (#51)

Co-authored-by: Vivek Yadav <[email protected]>

---------

Co-authored-by: Taher Lakdawala <[email protected]>
Co-authored-by: taherkl <[email protected]>
Co-authored-by: Vivek Yadav <[email protected]>
Co-authored-by: Vivek Yadav <[email protected]>
  • Loading branch information
5 people authored Jan 16, 2025
1 parent bc21bb4 commit f31babd
Show file tree
Hide file tree
Showing 10 changed files with 1,642 additions and 49 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/integration-tests-against-emulator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ jobs:
MYSQLUSER: root
MYSQLDATABASE: test_interleave_table_data
MYSQLDB_FKACTION: test_foreign_key_action_data
MYSQLDB_CHECK_CONSTRAINT: test_mysql_checkconstraint
MYSQLPWD: root

# set DynamoDB related environment variables
Expand Down Expand Up @@ -112,6 +113,7 @@ jobs:
- run: mysql -v -P 3306 --protocol=tcp -u root -proot test < test_data/mysqldump.test.out
- run: mysql -v -P 3306 --protocol=tcp -u root -proot < test_data/mysql_interleave_dump.test.out
- run: mysql -v -P 3306 --protocol=tcp -u root -proot < test_data/mysql_foreignkeyaction_dump.test.out
- run: mysql -v -P 3306 --protocol=tcp -u root -proot < test_data/mysql_checkconstraint_dump.test.out

# init sql server with test_data
# since we use ubuntu-latest container, we should ensure that the path matches the latest from https://packages.microsoft.com/config/ubuntu/
Expand Down
2 changes: 2 additions & 0 deletions conversion/conversion_from_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ func (sads *SchemaFromSourceImpl) SchemaFromDump(SpProjectId string, SpInstanceI
conv := internal.MakeConv()
conv.SpDialect = spDialect
conv.Source = driver
conv.SpProjectId = SpProjectId
conv.SpInstanceId = SpInstanceId
p := internal.NewProgress(n, "Generating schema", internal.Verbose(), false, int(internal.SchemaCreationInProgress))
r := internal.NewReader(bufio.NewReader(f), p)
conv.SetSchemaMode() // Build schema and ignore data in dump.
Expand Down
37 changes: 19 additions & 18 deletions sources/common/toddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,28 +192,29 @@ func (ss *SchemaToSpannerImpl) VerifyExpressions(conv *internal.Conv) error {
Source: conv.Source,
ExpressionDetailList: GenerateExpressionDetailList(spschema),
}

result := ss.ExpressionVerificationAccessor.VerifyExpressions(ctx, verifyExpressionsInput)
if result.ExpressionVerificationOutputList == nil {
return result.Err
}
issueTypes := GetIssue(result)
if len(issueTypes) > 0 {
for tableId, issues := range issueTypes {

for _, issue := range issues {
if _, exists := conv.SchemaIssues[tableId]; !exists {
conv.SchemaIssues[tableId] = internal.TableIssues{
TableLevelIssues: []internal.SchemaIssue{},
if len(verifyExpressionsInput.ExpressionDetailList) != 0 {
result := ss.ExpressionVerificationAccessor.VerifyExpressions(ctx, verifyExpressionsInput)
if result.ExpressionVerificationOutputList == nil {
return result.Err
}
issueTypes := GetIssue(result)
if len(issueTypes) > 0 {
for tableId, issues := range issueTypes {

for _, issue := range issues {
if _, exists := conv.SchemaIssues[tableId]; !exists {
conv.SchemaIssues[tableId] = internal.TableIssues{
TableLevelIssues: []internal.SchemaIssue{},
}
}
}

tableIssue := conv.SchemaIssues[tableId]
tableIssue := conv.SchemaIssues[tableId]

if !IsSchemaIssuePresent(tableIssue.TableLevelIssues, issue) {
tableIssue.TableLevelIssues = append(tableIssue.TableLevelIssues, issue)
if !IsSchemaIssuePresent(tableIssue.TableLevelIssues, issue) {
tableIssue.TableLevelIssues = append(tableIssue.TableLevelIssues, issue)
}
conv.SchemaIssues[tableId] = tableIssue
}
conv.SchemaIssues[tableId] = tableIssue
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions sources/mysql/infoschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,13 +344,24 @@ func (isi InfoSchemaImpl) processRow(
// Case added to handle check constraints
case "CHECK":
checkClause = collationRegex.ReplaceAllString(checkClause, "")
checkClause = checkAndAddParentheses(checkClause)
*checkKeys = append(*checkKeys, schema.CheckConstraint{Name: constraintName, Expr: checkClause, ExprId: internal.GenerateExpressionId(), Id: internal.GenerateCheckConstrainstId()})
default:
m[col] = append(m[col], constraintType)
}
return nil
}

// checkAndAddParentheses this method will check parentheses if found it will return same string
// or add the parentheses then return the string
func checkAndAddParentheses(checkClause string) string {
if strings.HasPrefix(checkClause, "(") && strings.HasSuffix(checkClause, ")") {
return checkClause
} else {
return `(` + checkClause + `)`
}
}

// GetForeignKeys return list all the foreign keys constraints.
// MySQL supports cross-database foreign key constraints. We ignore
// them because the Spanner migration tool works database at a time (a specific run
Expand Down
1 change: 1 addition & 0 deletions sources/mysql/mysqldump.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ func getCheckConstraints(constraints []*ast.Constraint) (checkConstraints []sche
if constraint.Tp == ast.ConstraintCheck {
exp := expressionToString(constraint.Expr)
exp = dbcollationRegex.ReplaceAllString(exp, "$1")
exp = checkAndAddParentheses(exp)
checkConstraint := schema.CheckConstraint{
Name: constraint.Name,
Expr: exp,
Expand Down
71 changes: 71 additions & 0 deletions test_data/mysql_checkconstraint_dump.test.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
-- MySQL dump 10.13 Distrib 8.3.0, for macos13.6 (arm64)
--
-- Host: 127.0.0.1 Database: test_mysql_checkconstraint
-- ------------------------------------------------------
-- Server version 8.0.40

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Current Database: `test_mysql_checkconstraint`
--

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test_mysql_checkconstraint` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*!80016 DEFAULT ENCRYPTION='N' */;

USE `test_mysql_checkconstraint`;

--
-- Table structure for table `TestTable`
--

DROP TABLE IF EXISTS `TestTable`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `TestTable` (
`ID` bigint NOT NULL,
`Value` bigint DEFAULT NULL,
`Flag` tinyint(1) DEFAULT NULL,
`Date` timestamp NULL DEFAULT NULL,
`Name` varchar(255) DEFAULT NULL,
`EnumValue` enum('OptionA','OptionB','OptionC') DEFAULT NULL,
`BooleanValue` tinyint DEFAULT NULL,
PRIMARY KEY (`ID`),
CONSTRAINT `chk_bitwise` CHECK (((`Value` & 2) = 0)),
CONSTRAINT `chk_Boolean` CHECK ((`BooleanValue` in (0,1))),
CONSTRAINT `chk_DateRange` CHECK ((`Date` between '2000-01-01 00:00:00' and '2100-12-31 23:59:59')),
CONSTRAINT `chk_Enum` CHECK ((`EnumValue` in ('OptionA','OptionB','OptionC'))),
CONSTRAINT `chk_NullValue` CHECK ((`Value` is not null)),
CONSTRAINT `chk_range` CHECK (((`Value` > 10) and (`Value` < 1000))),
CONSTRAINT `chk_StringLength` CHECK ((char_length(`Name`) > 5))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `TestTable`
--

LOCK TABLES `TestTable` WRITE;
/*!40000 ALTER TABLE `TestTable` DISABLE KEYS */;
INSERT INTO `TestTable` VALUES (1,12,1,'2023-10-08 03:30:00','ExampleName','OptionA',1);
/*!40000 ALTER TABLE `TestTable` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2025-01-08 16:06:14
Loading

0 comments on commit f31babd

Please sign in to comment.