Skip to content

Commit 33cbfe9

Browse files
authoredJan 7, 2025
test: fix generate_column integration test case (pingcap#797)
Signed-off-by: dongmen <414110582@qq.com>
1 parent fa5394f commit 33cbfe9

12 files changed

+265
-23
lines changed
 

‎.github/pull_request_template.md

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!--
2+
Thank you for contributing to TiCDC!
3+
Please read MD's [CONTRIBUTING](https://github.com/pingcap/ticdc/blob/master/CONTRIBUTING.md) document **BEFORE** filing this PR.
4+
-->
5+
6+
### What problem does this PR solve?
7+
<!--
8+
Please create an issue first to describe the problem.
9+
10+
There MUST be one line starting with "Issue Number: " and
11+
linking the relevant issues via the "close" or "ref".
12+
13+
For more info, check https://pingcap.github.io/tidb-dev-guide/contribute-to-tidb/contribute-code.html#referring-to-an-issue.
14+
-->
15+
16+
Issue Number: close #xxx
17+
18+
### What is changed and how it works?
19+
20+
### Check List <!--REMOVE the items that are not applicable-->
21+
22+
#### Tests <!-- At least one of them must be included. -->
23+
24+
- Unit test
25+
- Integration test
26+
- Manual test (add detailed scripts or steps below)
27+
- No code
28+
29+
#### Questions <!-- Authors should answer these questions and reviewers should consider these questions. -->
30+
31+
##### Will it cause performance regression or break compatibility?
32+
33+
##### Do you need to update user documentation, design documentation or monitoring documentation?
34+
35+
### Release note <!-- bugfixes or new features need a release note -->
36+
37+
```release-note
38+
Please refer to [Release Notes Language Style Guide](https://pingcap.github.io/tidb-dev-guide/contribute-to-tidb/release-notes-style-guide.html) to write a quality release note.
39+
40+
If you don't think this PR needs a release note then fill it with `None`.
41+
```

‎.github/workflows/check_and_build.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ on:
1212
- 'OWNERS_ALIASES'
1313

1414
pull_request:
15+
types: [opened, synchronize, reopened, ready_for_review]
1516
branches:
1617
- master
1718
- "release-[0-9].[0-9]*"

‎.github/workflows/integration_test_mysql.yaml

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ on:
1212
- 'OWNERS_ALIASES'
1313

1414
pull_request:
15+
types: [opened, synchronize, reopened, ready_for_review]
1516
branches:
1617
- master
1718
- "release-[0-9].[0-9]*"
@@ -30,7 +31,7 @@ jobs:
3031
# To boost the test speed, we split every 10 test cases into a group.
3132
e2e_test_group_1:
3233
runs-on: ubuntu-latest
33-
name: E2E Test
34+
name: E2E Test Group 1
3435
steps:
3536
- name: Check out code
3637
uses: actions/checkout@v2
@@ -82,6 +83,12 @@ jobs:
8283
run: |
8384
export TICDC_NEWARCH=true && make integration_test CASE=foreign_key
8485
86+
# The 7th case in this group
87+
- name: Test generate_column
88+
if: ${{ success() }}
89+
run: |
90+
export TICDC_NEWARCH=true && make integration_test CASE=generate_column
91+
8592
- name: Upload test logs
8693
if: always()
8794
uses: ./.github/actions/upload-test-logs

‎.github/workflows/uint_test.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ on:
1212
- 'OWNERS_ALIASES'
1313

1414
pull_request:
15+
types: [opened, synchronize, reopened, ready_for_review]
1516
branches:
1617
- master
1718
- "release-[0-9].[0-9]*"

‎CONTRIBUTING.md

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# How to contribute
2+
3+
This document outlines some of the conventions on development workflow, commit
4+
message formatting, contact points and other resources to make it easier to get
5+
your contribution accepted.
6+
7+
## Get started
8+
9+
- Fork the repository on GitHub.
10+
- Read the README.md for build instructions.
11+
- Play with the project, submit bugs, submit patches!
12+
13+
## Build TiCDC
14+
15+
Developing TiCDC requires:
16+
17+
* [Go 1.23+](https://go.dev/doc/code)
18+
* An internet connection to download the dependencies
19+
20+
Simply run `make cdc` to build the program.
21+
22+
```sh
23+
make cdc
24+
```
25+
26+
### Run tests
27+
28+
TODO
29+
30+
### Update dependencies
31+
32+
TiCDC uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. To add or update a dependency: use the `go mod edit` command to change the dependency.
33+
34+
## Contribution flow
35+
36+
This is a rough outline of what a contributor's workflow looks like:
37+
38+
- Create a topic branch from where you want to base your work. This is usually `master`.
39+
- Make commits of logical units and add test case if the change fixes a bug or adds new functionality.
40+
- Run tests and make sure all the tests are passed.
41+
- Make sure your commit messages are in the proper format (see below).
42+
- Push your changes to a topic branch in your fork of the repository.
43+
- Submit a pull request.
44+
- Your PR must receive LGTMs from two maintainers.
45+
46+
Thanks for your contributions!
47+
48+
### Code style
49+
50+
The coding style suggested by the Golang community is used in TiCDC. See the [style doc](https://github.com/golang/go/wiki/CodeReviewComments) for details.
51+
52+
Please follow this style to make TiCDC easy to review, maintain and develop.
53+
54+
### Commit message format
55+
56+
We follow a rough convention for commit messages that is designed to answer two
57+
questions: what changed and why. The subject line should feature the what and
58+
the body of the commit should describe the why.
59+
60+
```shell
61+
maintainer: add comment for variable declaration
62+
63+
Improve documentation.
64+
```
65+
66+
The format can be described more formally as follows:
67+
68+
```shell
69+
<subsystem>: <what changed>
70+
<BLANK LINE>
71+
<why this change was made>
72+
<BLANK LINE>
73+
<footer>(optional)
74+
```
75+
76+
The first line is the subject and should be no longer than 70 characters, the second line is always blank, and other lines should be wrapped at 80 characters. This allows the message to be easier to read on GitHub as well as in various git tools.
77+
78+
- If the change affects more than one subsystem, use a comma to separate them like ```maintainer,dispatcher:```.
79+
- If the change affects many subsystems, use ```*``` instead, like ```*:```.
80+
81+
For the why part, if no specific reason for the change, you can use one of some generic reasons like "Improve documentation.", "Improve performance.", "Improve robustness.", "Improve test coverage."

‎pkg/common/table_info.go

+5
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ const (
7474
UnsignedFlag
7575
)
7676

77+
func NewColumnFlagType(flag ColumnFlagType) *ColumnFlagType {
78+
f := ColumnFlagType(flag)
79+
return &f
80+
}
81+
7782
// SetIsBinary sets BinaryFlag
7883
func (b *ColumnFlagType) SetIsBinary() {
7984
(*Flag)(b).Add(Flag(BinaryFlag))

‎pkg/common/table_info_helper.go

+11-6
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ func newColumnSchema(tableInfo *model.TableInfo, digest Digest) *columnSchema {
454454
ID: col.ID,
455455
IsPKHandle: pkIsHandle,
456456
Ft: col.FieldType.Clone(),
457-
VirtualGenCol: col.IsGenerated(),
457+
VirtualGenCol: !IsColCDCVisible(col),
458458
}
459459
colSchema.RowColFieldTps[col.ID] = colSchema.RowColInfos[i].Ft
460460
colSchema.RowColFieldTpsSlice = append(colSchema.RowColFieldTpsSlice, colSchema.RowColInfos[i].Ft)
@@ -751,12 +751,13 @@ func (s *columnSchema) genPreSQLInsert(isReplace bool, needPlaceHolder bool) str
751751
builder.WriteString("INSERT INTO %s")
752752
}
753753
builder.WriteString(" (")
754-
builder.WriteString(s.getColumnList(false))
754+
nonGeneratedColumnCount, columnList := s.getColumnList(false)
755+
builder.WriteString(columnList)
755756
builder.WriteString(") VALUES ")
756757

757758
if needPlaceHolder {
758759
builder.WriteString("(")
759-
builder.WriteString(placeHolder(len(s.Columns) - s.VirtualColumnCount))
760+
builder.WriteString(placeHolder(nonGeneratedColumnCount))
760761
builder.WriteString(")")
761762
}
762763
return builder.String()
@@ -766,7 +767,8 @@ func (s *columnSchema) genPreSQLUpdate() string {
766767
var builder strings.Builder
767768
builder.WriteString("UPDATE %s")
768769
builder.WriteString(" SET ")
769-
builder.WriteString(s.getColumnList(true))
770+
_, columnList := s.getColumnList(true)
771+
builder.WriteString(columnList)
770772
return builder.String()
771773
}
772774

@@ -784,12 +786,15 @@ func placeHolder(n int) string {
784786
return builder.String()
785787
}
786788

787-
func (s *columnSchema) getColumnList(isUpdate bool) string {
789+
// getColumnList returns non-generated columns number and column names
790+
func (s *columnSchema) getColumnList(isUpdate bool) (int, string) {
788791
var b strings.Builder
792+
nonGeneratedColumnCount := 0
789793
for i, col := range s.Columns {
790794
if col == nil || s.ColumnsFlag[col.ID].IsGeneratedColumn() {
791795
continue
792796
}
797+
nonGeneratedColumnCount++
793798
if i > 0 {
794799
b.WriteString(",")
795800
}
@@ -798,5 +803,5 @@ func (s *columnSchema) getColumnList(isUpdate bool) string {
798803
b.WriteString(" = ?")
799804
}
800805
}
801-
return b.String()
806+
return nonGeneratedColumnCount, b.String()
802807
}

‎pkg/common/table_info_helper_test.go

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package common
2+
3+
import (
4+
"testing"
5+
6+
"github.com/pingcap/tidb/pkg/meta/model"
7+
pmodel "github.com/pingcap/tidb/pkg/parser/model"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestColumnSchema_GetColumnList(t *testing.T) {
12+
tests := []struct {
13+
name string
14+
columns []*model.ColumnInfo
15+
columnsFlag map[int64]*ColumnFlagType
16+
isUpdate bool
17+
wantCount int
18+
wantColumnList string
19+
}{
20+
{
21+
name: "normal columns without update",
22+
columns: []*model.ColumnInfo{
23+
{Name: pmodel.CIStr{O: "id", L: "id"}, ID: 1},
24+
{Name: pmodel.CIStr{O: "name", L: "name"}, ID: 2},
25+
{Name: pmodel.CIStr{O: "age", L: "age"}, ID: 3},
26+
},
27+
columnsFlag: map[int64]*ColumnFlagType{
28+
1: NewColumnFlagType(PrimaryKeyFlag),
29+
2: NewColumnFlagType(UniqueKeyFlag),
30+
3: NewColumnFlagType(NullableFlag),
31+
},
32+
isUpdate: false,
33+
wantCount: 3,
34+
wantColumnList: "`id`,`name`,`age`",
35+
},
36+
{
37+
name: "normal columns with update",
38+
columns: []*model.ColumnInfo{
39+
{Name: pmodel.CIStr{O: "id", L: "id"}, ID: 1},
40+
{Name: pmodel.CIStr{O: "name", L: "name"}, ID: 2},
41+
{Name: pmodel.CIStr{O: "age", L: "age"}, ID: 3},
42+
},
43+
columnsFlag: map[int64]*ColumnFlagType{
44+
1: NewColumnFlagType(PrimaryKeyFlag),
45+
2: NewColumnFlagType(UniqueKeyFlag),
46+
3: NewColumnFlagType(NullableFlag),
47+
},
48+
isUpdate: true,
49+
wantCount: 3,
50+
wantColumnList: "`id` = ?,`name` = ?,`age` = ?",
51+
},
52+
{
53+
name: "with generated columns",
54+
columns: []*model.ColumnInfo{
55+
{Name: pmodel.CIStr{O: "id", L: "id"}, ID: 1},
56+
{Name: pmodel.CIStr{O: "name", L: "name"}, ID: 2},
57+
{Name: pmodel.CIStr{O: "full_name", L: "full_name"}, ID: 3}, // generated column
58+
},
59+
columnsFlag: map[int64]*ColumnFlagType{
60+
1: NewColumnFlagType(PrimaryKeyFlag),
61+
2: NewColumnFlagType(UniqueKeyFlag),
62+
3: NewColumnFlagType(GeneratedColumnFlag),
63+
},
64+
isUpdate: false,
65+
wantCount: 2,
66+
wantColumnList: "`id`,`name`",
67+
},
68+
{
69+
name: "with nil column",
70+
columns: []*model.ColumnInfo{
71+
{Name: pmodel.CIStr{O: "id", L: "id"}, ID: 1},
72+
nil,
73+
{Name: pmodel.CIStr{O: "age", L: "age"}, ID: 3},
74+
},
75+
columnsFlag: map[int64]*ColumnFlagType{
76+
1: NewColumnFlagType(PrimaryKeyFlag),
77+
3: NewColumnFlagType(NullableFlag),
78+
},
79+
isUpdate: false,
80+
wantCount: 2,
81+
wantColumnList: "`id`,`age`",
82+
},
83+
}
84+
85+
for _, tt := range tests {
86+
t.Run(tt.name, func(t *testing.T) {
87+
s := &columnSchema{
88+
Columns: tt.columns,
89+
ColumnsFlag: tt.columnsFlag,
90+
}
91+
gotCount, gotColumnList := s.getColumnList(tt.isUpdate)
92+
require.Equal(t, tt.wantCount, gotCount)
93+
require.Equal(t, tt.wantColumnList, gotColumnList)
94+
})
95+
}
96+
}

‎pkg/sink/mysql/mysql_writer.go

+7
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"github.com/pingcap/tiflow/pkg/retry"
4040
pmysql "github.com/pingcap/tiflow/pkg/sink/mysql"
4141
"go.uber.org/zap"
42+
"go.uber.org/zap/zapcore"
4243
)
4344

4445
const (
@@ -748,6 +749,12 @@ func (w *MysqlWriter) prepareDMLs(events []*commonEvent.DMLEvent) (*preparedDMLs
748749
}
749750
}
750751

752+
// Pre-check log level to avoid dmls.String() being called unnecessarily
753+
// This method is expensive, so we only log it when the log level is debug.
754+
if log.GetLevel() == zapcore.DebugLevel {
755+
log.Debug("prepareDMLs", zap.Any("dmls", dmls.String()), zap.Any("events", events))
756+
}
757+
751758
return dmls, nil
752759
}
753760

‎pkg/sink/mysql/sql_builder.go

+14
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package mysql
1515

1616
import (
17+
"fmt"
1718
"strings"
1819
"sync"
1920

@@ -33,6 +34,19 @@ type preparedDMLs struct {
3334
startTs []uint64
3435
}
3536

37+
func (d *preparedDMLs) String() string {
38+
return fmt.Sprintf("sqls: %v, values: %v, rowCount: %d, approximateSize: %d, startTs: %v", d.fmtSqls(), d.values, d.rowCount, d.approximateSize, d.startTs)
39+
}
40+
41+
func (d *preparedDMLs) fmtSqls() string {
42+
builder := strings.Builder{}
43+
for _, sql := range d.sqls {
44+
builder.WriteString(sql)
45+
builder.WriteString(";")
46+
}
47+
return builder.String()
48+
}
49+
3650
var dmlsPool = sync.Pool{
3751
New: func() interface{} {
3852
return &preparedDMLs{

‎tests/integration_tests/generate_column/data/virtual.sql

-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,6 @@ drop database if exists `generate_column`;
22
create database `generate_column`;
33
use `generate_column`;
44

5-
create table t (a int, b int as (a + 1) stored primary key);
6-
insert into t(a) values (1),(2), (3),(4),(5),(6),(7);
7-
update t set a = 10 where a = 1;
8-
update t set a = 11 where b = 3;
9-
delete from t where b=4;
10-
delete from t where a=4;
11-
125
create table t1 (a int, b int as (a + 1) virtual not null, c int not null, unique index idx1(b), unique index idx2(c));
136
insert into t1 (a, c) values (1, 2),(2, 3), (3, 4),(4, 5),(5, 6),(6, 7),(7, 8);
147
update t1 set a = 10 where a = 1;

‎utils/dynstream/parallel_dynamic_stream.go

-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99

1010
"github.com/pingcap/log"
1111
. "github.com/pingcap/ticdc/pkg/apperror"
12-
"go.uber.org/zap"
1312
)
1413

1514
// Use a hasher to select target stream for the path.
@@ -93,14 +92,6 @@ func (s *parallelDynamicStream[A, P, T, D, H]) Push(path P, e T) {
9392
timestamp: s.handler.GetTimestamp(e),
9493
queueTime: time.Now(),
9594
}
96-
if s.memControl != nil {
97-
log.Debug("fizz: add event to stream",
98-
zap.Any("rawSize", s.handler.GetSize(e)),
99-
zap.Any("extraSize", s.eventExtraSize),
100-
zap.Any("totalSize", s.eventExtraSize+s.handler.GetSize(e)),
101-
zap.Any("event", e),
102-
)
103-
}
10495
pi.stream.in() <- ew
10596
}
10697

0 commit comments

Comments
 (0)
Please sign in to comment.