diff --git a/tests/basic/run.sh b/tests/basic/run.sh index c160469d..5b20a8c2 100644 --- a/tests/basic/run.sh +++ b/tests/basic/run.sh @@ -40,6 +40,27 @@ expected=$(seq 3 9) echo "expected ${expected}, actual ${actual}" [ "$actual" = "$expected" ] +# Test for OR WHERE case. Better dump MySQL here because Dumpling has some special handle for concurrently dump TiDB tables. +export DUMPLING_TEST_PORT=3306 +run_sql "drop database if exists \`$DB_NAME\`;" +run_sql "create database \`$DB_NAME\`;" +run_sql "create table \`$DB_NAME\`.\`$TABLE_NAME\` (a int primary key, b int);" + +seq 0 99 | xargs -I_ run_sql "insert into \`$DB_NAME\`.\`$TABLE_NAME\` (a,b) values (_, 99-_);" +run_sql "analyze table \`$DB_NAME\`.\`$TABLE_NAME\`;" +run_dumpling --where "b <= 4 or b >= 95" -f "$DB_NAME.$TABLE_NAME" --rows 10 + +actual=$(grep -w "(.*)" ${DUMPLING_OUTPUT_DIR}/${DB_NAME}.${TABLE_NAME}.000000000.sql | cut -c2-2) +expected=$(seq 0 4) +echo "expected ${DUMPLING_OUTPUT_DIR}/${DB_NAME}.${TABLE_NAME}.000000000.sql ${expected}, actual ${actual}" +[ "$actual" = "$expected" ] +actual=$(grep -w "(.*)" ${DUMPLING_OUTPUT_DIR}/${DB_NAME}.${TABLE_NAME}.000000009.sql | cut -c2-3) +expected=$(seq 95 99) +echo "expected ${DUMPLING_OUTPUT_DIR}/${DB_NAME}.${TABLE_NAME}.000000009.sql ${expected}, actual ${actual}" +[ "$actual" = "$expected" ] + +seq 1 8 | xargs -I\? file_not_exist ${DUMPLING_OUTPUT_DIR}/${DB_NAME}.${TABLE_NAME}.00000000\?.sql + # Test for specifying --filetype sql with --sql, should report an error set +e run_dumpling --sql "select * from \`$DB_NAME\`.\`$TABLE_NAME\`" --filetype sql > ${DUMPLING_OUTPUT_DIR}/dumpling.log diff --git a/v4/export/sql.go b/v4/export/sql.go index 56b4a9c9..0b939479 100644 --- a/v4/export/sql.go +++ b/v4/export/sql.go @@ -1069,18 +1069,24 @@ func parseSnapshotToTSO(pool *sql.DB, snapshot string) (uint64, error) { func buildWhereCondition(conf *Config, where string) string { var query strings.Builder separator := "WHERE" + leftBracket := " " + rightBracket := " " + if conf.Where != "" && where != "" { + leftBracket = " (" + rightBracket = ") " + } if conf.Where != "" { query.WriteString(separator) - query.WriteByte(' ') + query.WriteString(leftBracket) query.WriteString(conf.Where) - query.WriteByte(' ') + query.WriteString(rightBracket) separator = "AND" - query.WriteByte(' ') } if where != "" { query.WriteString(separator) - query.WriteString(" ") + query.WriteString(leftBracket) query.WriteString(where) + query.WriteString(rightBracket) } return query.String() } diff --git a/v4/export/sql_test.go b/v4/export/sql_test.go index dac6ff6b..ba9ac589 100644 --- a/v4/export/sql_test.go +++ b/v4/export/sql_test.go @@ -828,6 +828,43 @@ func TestBuildPartitionClauses(t *testing.T) { } } +func TestBuildWhereCondition(t *testing.T) { + t.Parallel() + + conf := DefaultConfig() + testCases := []struct { + confWhere string + chunkWhere string + expectedWhere string + }{ + { + "", + "", + "", + }, + { + "a >= 1000000 and a <= 2000000", + "", + "WHERE a >= 1000000 and a <= 2000000 ", + }, + { + "", + "(`a`>1 and `a`<3)or(`a`=1 and(`b`>=2))or(`a`=3 and(`b`<4))", + "WHERE (`a`>1 and `a`<3)or(`a`=1 and(`b`>=2))or(`a`=3 and(`b`<4)) ", + }, + { + "a >= 1000000 and a <= 2000000", + "(`a`>1 and `a`<3)or(`a`=1 and(`b`>=2))or(`a`=3 and(`b`<4))", + "WHERE (a >= 1000000 and a <= 2000000) AND ((`a`>1 and `a`<3)or(`a`=1 and(`b`>=2))or(`a`=3 and(`b`<4))) ", + }, + } + for _, testCase := range testCases { + conf.Where = testCase.confWhere + where := buildWhereCondition(conf, testCase.chunkWhere) + require.Equal(t, testCase.expectedWhere, where) + } +} + func TestBuildRegionQueriesWithoutPartition(t *testing.T) { t.Parallel()