exploded args on range query building; iteration works

This commit is contained in:
Shlomi Noach 2016-04-05 19:50:49 +02:00
parent 3583ab5dc5
commit d8fefb3d6f
5 changed files with 112 additions and 78 deletions

View File

@ -11,7 +11,6 @@ import (
"github.com/github/gh-osc/go/base" "github.com/github/gh-osc/go/base"
"github.com/github/gh-osc/go/mysql" "github.com/github/gh-osc/go/mysql"
"github.com/github/gh-osc/go/sql" "github.com/github/gh-osc/go/sql"
"reflect"
"github.com/outbrain/golib/log" "github.com/outbrain/golib/log"
"github.com/outbrain/golib/sqlutils" "github.com/outbrain/golib/sqlutils"
@ -156,17 +155,17 @@ func (this *Applier) IterationIsComplete() (bool, error) {
if this.migrationContext.MigrationIterationRangeMinValues == nil { if this.migrationContext.MigrationIterationRangeMinValues == nil {
return false, nil return false, nil
} }
compareWithIterationRangeStart, err := sql.BuildRangePreparedComparison(this.migrationContext.UniqueKey.Columns, sql.GreaterThanOrEqualsComparisonSign)
if err != nil {
return false, err
}
compareWithRangeEnd, err := sql.BuildRangePreparedComparison(this.migrationContext.UniqueKey.Columns, sql.LessThanComparisonSign)
if err != nil {
return false, err
}
args := sqlutils.Args() args := sqlutils.Args()
args = append(args, this.migrationContext.MigrationIterationRangeMinValues.AbstractValues()...) compareWithIterationRangeStart, explodedArgs, err := sql.BuildRangePreparedComparison(this.migrationContext.UniqueKey.Columns, this.migrationContext.MigrationIterationRangeMinValues.AbstractValues(), sql.GreaterThanOrEqualsComparisonSign)
args = append(args, this.migrationContext.MigrationRangeMaxValues.AbstractValues()...) if err != nil {
return false, err
}
args = append(args, explodedArgs...)
compareWithRangeEnd, explodedArgs, err := sql.BuildRangePreparedComparison(this.migrationContext.UniqueKey.Columns, this.migrationContext.MigrationRangeMaxValues.AbstractValues(), sql.LessThanComparisonSign)
if err != nil {
return false, err
}
args = append(args, explodedArgs...)
query := fmt.Sprintf(` query := fmt.Sprintf(`
select /* gh-osc IterationIsComplete */ 1 select /* gh-osc IterationIsComplete */ 1
from %s.%s from %s.%s
@ -178,13 +177,12 @@ func (this *Applier) IterationIsComplete() (bool, error) {
compareWithIterationRangeStart, compareWithIterationRangeStart,
compareWithRangeEnd, compareWithRangeEnd,
) )
log.Debugf(query)
moreRowsFound := false moreRowsFound := false
err = sqlutils.QueryRowsMap(this.db, query, func(rowMap sqlutils.RowMap) error { err = sqlutils.QueryRowsMap(this.db, query, func(rowMap sqlutils.RowMap) error {
moreRowsFound = true moreRowsFound = true
return nil return nil
}, args) }, args...)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -192,16 +190,24 @@ func (this *Applier) IterationIsComplete() (bool, error) {
} }
func (this *Applier) CalculateNextIterationRangeEndValues() error { func (this *Applier) CalculateNextIterationRangeEndValues() error {
query, err := sql.BuildUniqueKeyRangeEndPreparedQuery(this.migrationContext.DatabaseName, this.migrationContext.OriginalTableName, this.migrationContext.UniqueKey.Columns, this.migrationContext.ChunkSize)
if err != nil {
return err
}
startingFromValues := this.migrationContext.MigrationRangeMinValues startingFromValues := this.migrationContext.MigrationRangeMinValues
this.migrationContext.MigrationIterationRangeMinValues = this.migrationContext.MigrationIterationRangeMaxValues this.migrationContext.MigrationIterationRangeMinValues = this.migrationContext.MigrationIterationRangeMaxValues
if this.migrationContext.MigrationIterationRangeMinValues != nil { if this.migrationContext.MigrationIterationRangeMinValues != nil {
startingFromValues = this.migrationContext.MigrationIterationRangeMinValues startingFromValues = this.migrationContext.MigrationIterationRangeMinValues
} }
rows, err := this.db.Query(query, startingFromValues.AbstractValues()...) query, explodedArgs, err := sql.BuildUniqueKeyRangeEndPreparedQuery(
this.migrationContext.DatabaseName,
this.migrationContext.OriginalTableName,
this.migrationContext.UniqueKey.Columns,
startingFromValues.AbstractValues(),
this.migrationContext.MigrationRangeMaxValues.AbstractValues(),
this.migrationContext.ChunkSize,
fmt.Sprintf("iteration:%d", this.migrationContext.Iteration),
)
if err != nil {
return err
}
rows, err := this.db.Query(query, explodedArgs...)
if err != nil { if err != nil {
return err return err
} }
@ -213,12 +219,12 @@ func (this *Applier) CalculateNextIterationRangeEndValues() error {
} }
iterationRangeEndFound = true iterationRangeEndFound = true
} }
log.Debugf("5")
if !iterationRangeEndFound { if !iterationRangeEndFound {
return fmt.Errorf("Cannot find iteration range end") log.Debugf("Iteration complete: cannot find iteration end")
return nil
} }
this.migrationContext.MigrationIterationRangeMaxValues = iterationRangeMaxValues this.migrationContext.MigrationIterationRangeMaxValues = iterationRangeMaxValues
log.Debugf("column values: %s", this.migrationContext.MigrationIterationRangeMaxValues) log.Debugf("column values: %s; iteration: %d; chunk-size: %d", this.migrationContext.MigrationIterationRangeMaxValues, this.migrationContext.Iteration, this.migrationContext.ChunkSize)
return nil return nil
} }
@ -238,10 +244,6 @@ func (this *Applier) IterateTable(uniqueKey *sql.UniqueKey) error {
if err = rows.Scan(columnValues.ValuesPointers...); err != nil { if err = rows.Scan(columnValues.ValuesPointers...); err != nil {
return err return err
} }
for _, val := range columnValues.BinaryValues() {
log.Debugf("%s", reflect.TypeOf(val))
log.Debugf("%s", string(val))
}
} }
log.Debugf("column values: %s", columnValues) log.Debugf("column values: %s", columnValues)
query = `insert into test.sample_data_dump (category, ts) values (?, ?)` query = `insert into test.sample_data_dump (category, ts) values (?, ?)`

View File

@ -56,12 +56,10 @@ func (this *Migrator) Migrate() (err error) {
// return err // return err
// } // }
this.migrationContext.UniqueKey = uniqueKeys[0] this.migrationContext.UniqueKey = uniqueKeys[0]
this.migrationContext.ChunkSize = 100
if err := this.applier.ReadMigrationRangeValues(); err != nil { if err := this.applier.ReadMigrationRangeValues(); err != nil {
return err return err
} }
for { for {
log.Debugf("checking if complete")
isComplete, err := this.applier.IterationIsComplete() isComplete, err := this.applier.IterationIsComplete()
if err != nil { if err != nil {
return err return err
@ -73,6 +71,7 @@ func (this *Migrator) Migrate() (err error) {
if err != nil { if err != nil {
return err return err
} }
this.migrationContext.Iteration++
} }
if err := this.applier.IterateTable(uniqueKeys[0]); err != nil { if err := this.applier.IterateTable(uniqueKeys[0]); err != nil {
return err return err

View File

@ -64,12 +64,15 @@ func BuildEqualsComparison(columns []string, values []string) (result string, er
return result, nil return result, nil
} }
func BuildRangeComparison(columns []string, values []string, comparisonSign ValueComparisonSign) (result string, err error) { func BuildRangeComparison(columns []string, values []string, args []interface{}, comparisonSign ValueComparisonSign) (result string, explodedArgs []interface{}, err error) {
if len(columns) == 0 { if len(columns) == 0 {
return "", fmt.Errorf("Got 0 columns in GetRangeComparison") return "", explodedArgs, fmt.Errorf("Got 0 columns in GetRangeComparison")
} }
if len(columns) != len(values) { if len(columns) != len(values) {
return "", fmt.Errorf("Got %d columns but %d values in GetEqualsComparison", len(columns), len(values)) return "", explodedArgs, fmt.Errorf("Got %d columns but %d values in GetEqualsComparison", len(columns), len(values))
}
if len(columns) != len(args) {
return "", explodedArgs, fmt.Errorf("Got %d columns but %d args in GetEqualsComparison", len(columns), len(args))
} }
includeEquals := false includeEquals := false
if comparisonSign == LessThanOrEqualsComparisonSign { if comparisonSign == LessThanOrEqualsComparisonSign {
@ -87,43 +90,47 @@ func BuildRangeComparison(columns []string, values []string, comparisonSign Valu
value := values[i] value := values[i]
rangeComparison, err := BuildValueComparison(column, value, comparisonSign) rangeComparison, err := BuildValueComparison(column, value, comparisonSign)
if err != nil { if err != nil {
return "", err return "", explodedArgs, err
} }
if len(columns[0:i]) > 0 { if len(columns[0:i]) > 0 {
equalitiesComparison, err := BuildEqualsComparison(columns[0:i], values[0:i]) equalitiesComparison, err := BuildEqualsComparison(columns[0:i], values[0:i])
if err != nil { if err != nil {
return "", err return "", explodedArgs, err
} }
comparison := fmt.Sprintf("(%s AND %s)", equalitiesComparison, rangeComparison) comparison := fmt.Sprintf("(%s AND %s)", equalitiesComparison, rangeComparison)
comparisons = append(comparisons, comparison) comparisons = append(comparisons, comparison)
explodedArgs = append(explodedArgs, args[0:i]...)
explodedArgs = append(explodedArgs, args[i])
} else { } else {
comparisons = append(comparisons, rangeComparison) comparisons = append(comparisons, rangeComparison)
explodedArgs = append(explodedArgs, args[i])
} }
} }
if includeEquals { if includeEquals {
comparison, err := BuildEqualsComparison(columns, values) comparison, err := BuildEqualsComparison(columns, values)
if err != nil { if err != nil {
return "", nil return "", explodedArgs, nil
} }
comparisons = append(comparisons, comparison) comparisons = append(comparisons, comparison)
explodedArgs = append(explodedArgs, args...)
} }
result = strings.Join(comparisons, " or ") result = strings.Join(comparisons, " or ")
result = fmt.Sprintf("(%s)", result) result = fmt.Sprintf("(%s)", result)
return result, nil return result, explodedArgs, nil
} }
func BuildRangePreparedComparison(columns []string, comparisonSign ValueComparisonSign) (result string, err error) { func BuildRangePreparedComparison(columns []string, args []interface{}, comparisonSign ValueComparisonSign) (result string, explodedArgs []interface{}, err error) {
values := make([]string, len(columns), len(columns)) values := make([]string, len(columns), len(columns))
for i := range columns { for i := range columns {
values[i] = "?" values[i] = "?"
} }
return BuildRangeComparison(columns, values, comparisonSign) return BuildRangeComparison(columns, values, args, comparisonSign)
} }
func BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName string, sharedColumns []string, uniqueKey string, uniqueKeyColumns, rangeStartValues, rangeEndValues []string, includeRangeStartValues bool) (string, error) { func BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName string, sharedColumns []string, uniqueKey string, uniqueKeyColumns, rangeStartValues, rangeEndValues []string, rangeStartArgs, rangeEndArgs []interface{}, includeRangeStartValues bool) (result string, explodedArgs []interface{}, err error) {
if len(sharedColumns) == 0 { if len(sharedColumns) == 0 {
return "", fmt.Errorf("Got 0 shared columns in BuildRangeInsertQuery") return "", explodedArgs, fmt.Errorf("Got 0 shared columns in BuildRangeInsertQuery")
} }
databaseName = EscapeName(databaseName) databaseName = EscapeName(databaseName)
originalTableName = EscapeName(originalTableName) originalTableName = EscapeName(originalTableName)
@ -138,15 +145,17 @@ func BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName strin
if includeRangeStartValues { if includeRangeStartValues {
minRangeComparisonSign = GreaterThanOrEqualsComparisonSign minRangeComparisonSign = GreaterThanOrEqualsComparisonSign
} }
rangeStartComparison, err := BuildRangeComparison(uniqueKeyColumns, rangeStartValues, minRangeComparisonSign) rangeStartComparison, rangeExplodedArgs, err := BuildRangeComparison(uniqueKeyColumns, rangeStartValues, rangeStartArgs, minRangeComparisonSign)
if err != nil { if err != nil {
return "", err return "", explodedArgs, err
} }
rangeEndComparison, err := BuildRangeComparison(uniqueKeyColumns, rangeEndValues, LessThanOrEqualsComparisonSign) explodedArgs = append(explodedArgs, rangeExplodedArgs...)
rangeEndComparison, rangeExplodedArgs, err := BuildRangeComparison(uniqueKeyColumns, rangeEndValues, rangeEndArgs, LessThanOrEqualsComparisonSign)
if err != nil { if err != nil {
return "", err return "", explodedArgs, err
} }
query := fmt.Sprintf(` explodedArgs = append(explodedArgs, rangeExplodedArgs...)
result = fmt.Sprintf(`
insert /* gh-osc %s.%s */ ignore into %s.%s (%s) insert /* gh-osc %s.%s */ ignore into %s.%s (%s)
(select %s from %s.%s force index (%s) (select %s from %s.%s force index (%s)
where (%s and %s) where (%s and %s)
@ -154,34 +163,37 @@ func BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName strin
`, databaseName, originalTableName, databaseName, ghostTableName, sharedColumnsListing, `, databaseName, originalTableName, databaseName, ghostTableName, sharedColumnsListing,
sharedColumnsListing, databaseName, originalTableName, uniqueKey, sharedColumnsListing, databaseName, originalTableName, uniqueKey,
rangeStartComparison, rangeEndComparison) rangeStartComparison, rangeEndComparison)
return query, nil return result, explodedArgs, nil
} }
func BuildRangeInsertPreparedQuery(databaseName, originalTableName, ghostTableName string, sharedColumns []string, uniqueKey string, uniqueKeyColumns []string, includeRangeStartValues bool) (string, error) { func BuildRangeInsertPreparedQuery(databaseName, originalTableName, ghostTableName string, sharedColumns []string, uniqueKey string, uniqueKeyColumns []string, rangeStartArgs, rangeEndArgs []interface{}, includeRangeStartValues bool) (result string, explodedArgs []interface{}, err error) {
rangeStartValues := make([]string, len(uniqueKeyColumns), len(uniqueKeyColumns)) rangeStartValues := make([]string, len(uniqueKeyColumns), len(uniqueKeyColumns))
rangeEndValues := make([]string, len(uniqueKeyColumns), len(uniqueKeyColumns)) rangeEndValues := make([]string, len(uniqueKeyColumns), len(uniqueKeyColumns))
for i := range uniqueKeyColumns { for i := range uniqueKeyColumns {
rangeStartValues[i] = "?" rangeStartValues[i] = "?"
rangeEndValues[i] = "?" rangeEndValues[i] = "?"
} }
return BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, includeRangeStartValues) return BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, includeRangeStartValues)
} }
func BuildUniqueKeyRangeEndPreparedQuery(databaseName, tableName string, uniqueKeyColumns []string, chunkSize int) (string, error) { func BuildUniqueKeyRangeEndPreparedQuery(databaseName, tableName string, uniqueKeyColumns []string, rangeStartArgs, rangeEndArgs []interface{}, chunkSize int, hint string) (result string, explodedArgs []interface{}, err error) {
if len(uniqueKeyColumns) == 0 { if len(uniqueKeyColumns) == 0 {
return "", fmt.Errorf("Got 0 columns in BuildUniqueKeyRangeEndPreparedQuery") return "", explodedArgs, fmt.Errorf("Got 0 columns in BuildUniqueKeyRangeEndPreparedQuery")
} }
databaseName = EscapeName(databaseName) databaseName = EscapeName(databaseName)
tableName = EscapeName(tableName) tableName = EscapeName(tableName)
rangeStartComparison, err := BuildRangePreparedComparison(uniqueKeyColumns, GreaterThanComparisonSign) rangeStartComparison, rangeExplodedArgs, err := BuildRangePreparedComparison(uniqueKeyColumns, rangeStartArgs, GreaterThanComparisonSign)
if err != nil { if err != nil {
return "", err return "", explodedArgs, err
} }
rangeEndComparison, err := BuildRangePreparedComparison(uniqueKeyColumns, LessThanOrEqualsComparisonSign) explodedArgs = append(explodedArgs, rangeExplodedArgs...)
rangeEndComparison, rangeExplodedArgs, err := BuildRangePreparedComparison(uniqueKeyColumns, rangeEndArgs, LessThanOrEqualsComparisonSign)
if err != nil { if err != nil {
return "", err return "", explodedArgs, err
} }
explodedArgs = append(explodedArgs, rangeExplodedArgs...)
uniqueKeyColumnAscending := make([]string, len(uniqueKeyColumns), len(uniqueKeyColumns)) uniqueKeyColumnAscending := make([]string, len(uniqueKeyColumns), len(uniqueKeyColumns))
uniqueKeyColumnDescending := make([]string, len(uniqueKeyColumns), len(uniqueKeyColumns)) uniqueKeyColumnDescending := make([]string, len(uniqueKeyColumns), len(uniqueKeyColumns))
for i := range uniqueKeyColumns { for i := range uniqueKeyColumns {
@ -189,8 +201,8 @@ func BuildUniqueKeyRangeEndPreparedQuery(databaseName, tableName string, uniqueK
uniqueKeyColumnAscending[i] = fmt.Sprintf("%s asc", uniqueKeyColumns[i]) uniqueKeyColumnAscending[i] = fmt.Sprintf("%s asc", uniqueKeyColumns[i])
uniqueKeyColumnDescending[i] = fmt.Sprintf("%s desc", uniqueKeyColumns[i]) uniqueKeyColumnDescending[i] = fmt.Sprintf("%s desc", uniqueKeyColumns[i])
} }
query := fmt.Sprintf(` result = fmt.Sprintf(`
select /* gh-osc %s.%s */ %s select /* gh-osc %s.%s %s */ %s
from ( from (
select select
%s %s
@ -204,13 +216,13 @@ func BuildUniqueKeyRangeEndPreparedQuery(databaseName, tableName string, uniqueK
order by order by
%s %s
limit 1 limit 1
`, databaseName, tableName, strings.Join(uniqueKeyColumns, ", "), `, databaseName, tableName, hint, strings.Join(uniqueKeyColumns, ", "),
strings.Join(uniqueKeyColumns, ", "), databaseName, tableName, strings.Join(uniqueKeyColumns, ", "), databaseName, tableName,
rangeStartComparison, rangeEndComparison, rangeStartComparison, rangeEndComparison,
strings.Join(uniqueKeyColumnAscending, ", "), chunkSize, strings.Join(uniqueKeyColumnAscending, ", "), chunkSize,
strings.Join(uniqueKeyColumnDescending, ", "), strings.Join(uniqueKeyColumnDescending, ", "),
) )
return query, nil return result, explodedArgs, nil
} }
func BuildUniqueKeyMinValuesPreparedQuery(databaseName, tableName string, uniqueKeyColumns []string) (string, error) { func BuildUniqueKeyMinValuesPreparedQuery(databaseName, tableName string, uniqueKeyColumns []string) (string, error) {

View File

@ -8,6 +8,7 @@ package sql
import ( import (
"testing" "testing"
"reflect"
"regexp" "regexp"
"strings" "strings"
@ -71,48 +72,60 @@ func TestBuildRangeComparison(t *testing.T) {
{ {
columns := []string{"c1"} columns := []string{"c1"}
values := []string{"@v1"} values := []string{"@v1"}
comparison, err := BuildRangeComparison(columns, values, LessThanComparisonSign) args := []interface{}{3}
comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanComparisonSign)
test.S(t).ExpectNil(err) test.S(t).ExpectNil(err)
test.S(t).ExpectEquals(comparison, "((`c1` < @v1))") test.S(t).ExpectEquals(comparison, "((`c1` < @v1))")
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3}))
} }
{ {
columns := []string{"c1"} columns := []string{"c1"}
values := []string{"@v1"} values := []string{"@v1"}
comparison, err := BuildRangeComparison(columns, values, LessThanOrEqualsComparisonSign) args := []interface{}{3}
comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
test.S(t).ExpectNil(err) test.S(t).ExpectNil(err)
test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or ((`c1` = @v1)))") test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or ((`c1` = @v1)))")
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3}))
} }
{ {
columns := []string{"c1", "c2"} columns := []string{"c1", "c2"}
values := []string{"@v1", "@v2"} values := []string{"@v1", "@v2"}
comparison, err := BuildRangeComparison(columns, values, LessThanComparisonSign) args := []interface{}{3, 17}
comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanComparisonSign)
test.S(t).ExpectNil(err) test.S(t).ExpectNil(err)
test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or (((`c1` = @v1)) AND (`c2` < @v2)))") test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or (((`c1` = @v1)) AND (`c2` < @v2)))")
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17}))
} }
{ {
columns := []string{"c1", "c2"} columns := []string{"c1", "c2"}
values := []string{"@v1", "@v2"} values := []string{"@v1", "@v2"}
comparison, err := BuildRangeComparison(columns, values, LessThanOrEqualsComparisonSign) args := []interface{}{3, 17}
comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
test.S(t).ExpectNil(err) test.S(t).ExpectNil(err)
test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or (((`c1` = @v1)) AND (`c2` < @v2)) or ((`c1` = @v1) and (`c2` = @v2)))") test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or (((`c1` = @v1)) AND (`c2` < @v2)) or ((`c1` = @v1) and (`c2` = @v2)))")
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 3, 17}))
} }
{ {
columns := []string{"c1", "c2", "c3"} columns := []string{"c1", "c2", "c3"}
values := []string{"@v1", "@v2", "@v3"} values := []string{"@v1", "@v2", "@v3"}
comparison, err := BuildRangeComparison(columns, values, LessThanOrEqualsComparisonSign) args := []interface{}{3, 17, 22}
comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
test.S(t).ExpectNil(err) test.S(t).ExpectNil(err)
test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or (((`c1` = @v1)) AND (`c2` < @v2)) or (((`c1` = @v1) and (`c2` = @v2)) AND (`c3` < @v3)) or ((`c1` = @v1) and (`c2` = @v2) and (`c3` = @v3)))") test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or (((`c1` = @v1)) AND (`c2` < @v2)) or (((`c1` = @v1) and (`c2` = @v2)) AND (`c3` < @v3)) or ((`c1` = @v1) and (`c2` = @v2) and (`c3` = @v3)))")
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 3, 17, 22, 3, 17, 22}))
} }
{ {
columns := []string{"c1"} columns := []string{"c1"}
values := []string{"@v1", "@v2"} values := []string{"@v1", "@v2"}
_, err := BuildRangeComparison(columns, values, LessThanOrEqualsComparisonSign) args := []interface{}{3, 17}
_, _, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
test.S(t).ExpectNotNil(err) test.S(t).ExpectNotNil(err)
} }
{ {
columns := []string{} columns := []string{}
values := []string{} values := []string{}
_, err := BuildRangeComparison(columns, values, LessThanOrEqualsComparisonSign) args := []interface{}{}
_, _, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
test.S(t).ExpectNotNil(err) test.S(t).ExpectNotNil(err)
} }
} }
@ -127,8 +140,10 @@ func TestBuildRangeInsertQuery(t *testing.T) {
uniqueKeyColumns := []string{"id"} uniqueKeyColumns := []string{"id"}
rangeStartValues := []string{"@v1s"} rangeStartValues := []string{"@v1s"}
rangeEndValues := []string{"@v1e"} rangeEndValues := []string{"@v1e"}
rangeStartArgs := []interface{}{3}
rangeEndArgs := []interface{}{103}
query, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, true) query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true)
test.S(t).ExpectNil(err) test.S(t).ExpectNil(err)
expected := ` expected := `
insert /* gh-osc mydb.tbl */ ignore into mydb.ghost (id, name, position) insert /* gh-osc mydb.tbl */ ignore into mydb.ghost (id, name, position)
@ -137,14 +152,17 @@ func TestBuildRangeInsertQuery(t *testing.T) {
) )
` `
test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected)) test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 103, 103}))
} }
{ {
uniqueKey := "name_position_uidx" uniqueKey := "name_position_uidx"
uniqueKeyColumns := []string{"name", "position"} uniqueKeyColumns := []string{"name", "position"}
rangeStartValues := []string{"@v1s", "@v2s"} rangeStartValues := []string{"@v1s", "@v2s"}
rangeEndValues := []string{"@v1e", "@v2e"} rangeEndValues := []string{"@v1e", "@v2e"}
rangeStartArgs := []interface{}{3, 17}
rangeEndArgs := []interface{}{103, 117}
query, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, true) query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true)
test.S(t).ExpectNil(err) test.S(t).ExpectNil(err)
expected := ` expected := `
insert /* gh-osc mydb.tbl */ ignore into mydb.ghost (id, name, position) insert /* gh-osc mydb.tbl */ ignore into mydb.ghost (id, name, position)
@ -153,6 +171,7 @@ func TestBuildRangeInsertQuery(t *testing.T) {
) )
` `
test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected)) test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 3, 17, 103, 103, 117, 103, 117}))
} }
} }
@ -164,8 +183,10 @@ func TestBuildRangeInsertPreparedQuery(t *testing.T) {
{ {
uniqueKey := "name_position_uidx" uniqueKey := "name_position_uidx"
uniqueKeyColumns := []string{"name", "position"} uniqueKeyColumns := []string{"name", "position"}
rangeStartArgs := []interface{}{3, 17}
rangeEndArgs := []interface{}{103, 117}
query, err := BuildRangeInsertPreparedQuery(databaseName, originalTableName, ghostTableName, sharedColumns, uniqueKey, uniqueKeyColumns, true) query, explodedArgs, err := BuildRangeInsertPreparedQuery(databaseName, originalTableName, ghostTableName, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartArgs, rangeEndArgs, true)
test.S(t).ExpectNil(err) test.S(t).ExpectNil(err)
expected := ` expected := `
insert /* gh-osc mydb.tbl */ ignore into mydb.ghost (id, name, position) insert /* gh-osc mydb.tbl */ ignore into mydb.ghost (id, name, position)
@ -174,6 +195,7 @@ func TestBuildRangeInsertPreparedQuery(t *testing.T) {
) )
` `
test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected)) test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 3, 17, 103, 103, 117, 103, 117}))
} }
} }
@ -183,11 +205,13 @@ func TestBuildUniqueKeyRangeEndPreparedQuery(t *testing.T) {
chunkSize := 500 chunkSize := 500
{ {
uniqueKeyColumns := []string{"name", "position"} uniqueKeyColumns := []string{"name", "position"}
rangeStartArgs := []interface{}{3, 17}
rangeEndArgs := []interface{}{103, 117}
query, err := BuildUniqueKeyRangeEndPreparedQuery(databaseName, originalTableName, uniqueKeyColumns, chunkSize) query, explodedArgs, err := BuildUniqueKeyRangeEndPreparedQuery(databaseName, originalTableName, uniqueKeyColumns, rangeStartArgs, rangeEndArgs, chunkSize, "test")
test.S(t).ExpectNil(err) test.S(t).ExpectNil(err)
expected := ` expected := `
select /* gh-osc mydb.tbl */ name, position select /* gh-osc mydb.tbl test */ name, position
from ( from (
select select
name, position name, position
@ -203,6 +227,7 @@ func TestBuildUniqueKeyRangeEndPreparedQuery(t *testing.T) {
limit 1 limit 1
` `
test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected)) test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 103, 103, 117, 103, 117}))
} }
} }

View File

@ -65,18 +65,14 @@ func (this *ColumnValues) AbstractValues() []interface{} {
return this.abstractValues return this.abstractValues
} }
func (this *ColumnValues) BinaryValues() [][]uint8 {
result := make([][]uint8, len(this.abstractValues), len(this.abstractValues))
for i, val := range this.abstractValues {
result[i] = val.([]uint8)
}
return result
}
func (this *ColumnValues) String() string { func (this *ColumnValues) String() string {
stringValues := []string{} stringValues := []string{}
for _, val := range this.BinaryValues() { for _, val := range this.AbstractValues() {
stringValues = append(stringValues, string(val)) if ints, ok := val.([]uint8); ok {
stringValues = append(stringValues, string(ints))
} else {
stringValues = append(stringValues, fmt.Sprintf("%+v", val))
}
} }
return strings.Join(stringValues, ",") return strings.Join(stringValues, ",")
} }