зеркало из https://github.com/github/gh-ost.git
Cleanup whitespace and comments in SQL query text (#1246)
* Cleanup whitespace in SQL query text * cleanup * Add indent * Update unit tests * Update unit tests, pt 2 * Fix tweaks * Fix merge conflict resolution Signed-off-by: Tim Vaillancourt <tim@timvaillancourt.com> --------- Signed-off-by: Tim Vaillancourt <tim@timvaillancourt.com>
This commit is contained in:
Родитель
347d8e02dc
Коммит
5ebb95347e
|
@ -108,7 +108,7 @@ func (this *Applier) InitDBConnections() (err error) {
|
|||
|
||||
// validateAndReadTimeZone potentially reads server time-zone
|
||||
func (this *Applier) validateAndReadTimeZone() error {
|
||||
query := `select @@global.time_zone`
|
||||
query := `select /* gh-ost */ @@global.time_zone`
|
||||
if err := this.db.QueryRow(query).Scan(&this.migrationContext.ApplierTimeZone); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -392,14 +392,15 @@ func (this *Applier) WriteChangelog(hint, value string) (string, error) {
|
|||
explicitId = 3
|
||||
}
|
||||
query := fmt.Sprintf(`
|
||||
insert /* gh-ost */ into %s.%s
|
||||
(id, hint, value)
|
||||
values
|
||||
(NULLIF(?, 0), ?, ?)
|
||||
on duplicate key update
|
||||
last_update=NOW(),
|
||||
value=VALUES(value)
|
||||
`,
|
||||
insert /* gh-ost */
|
||||
into
|
||||
%s.%s
|
||||
(id, hint, value)
|
||||
values
|
||||
(NULLIF(?, 0), ?, ?)
|
||||
on duplicate key update
|
||||
last_update=NOW(),
|
||||
value=VALUES(value)`,
|
||||
sql.EscapeName(this.migrationContext.DatabaseName),
|
||||
sql.EscapeName(this.migrationContext.GetChangelogTableName()),
|
||||
)
|
||||
|
@ -854,7 +855,7 @@ func (this *Applier) GetSessionLockName(sessionId int64) string {
|
|||
// ExpectUsedLock expects the special hint voluntary lock to exist on given session
|
||||
func (this *Applier) ExpectUsedLock(sessionId int64) error {
|
||||
var result int64
|
||||
query := `select is_used_lock(?)`
|
||||
query := `select /* gh-ost */ is_used_lock(?)`
|
||||
lockName := this.GetSessionLockName(sessionId)
|
||||
this.migrationContext.Log.Infof("Checking session lock: %s", lockName)
|
||||
if err := this.db.QueryRow(query, lockName).Scan(&result); err != nil || result != sessionId {
|
||||
|
@ -867,14 +868,14 @@ func (this *Applier) ExpectUsedLock(sessionId int64) error {
|
|||
func (this *Applier) ExpectProcess(sessionId int64, stateHint, infoHint string) error {
|
||||
found := false
|
||||
query := `
|
||||
select id
|
||||
from information_schema.processlist
|
||||
where
|
||||
id != connection_id()
|
||||
and ? in (0, id)
|
||||
and state like concat('%', ?, '%')
|
||||
and info like concat('%', ?, '%')
|
||||
`
|
||||
select /* gh-ost */ id
|
||||
from
|
||||
information_schema.processlist
|
||||
where
|
||||
id != connection_id()
|
||||
and ? in (0, id)
|
||||
and state like concat('%', ?, '%')
|
||||
and info like concat('%', ?, '%')`
|
||||
err := sqlutils.QueryRowsMap(this.db, query, func(m sqlutils.RowMap) error {
|
||||
found = true
|
||||
return nil
|
||||
|
@ -912,10 +913,10 @@ func (this *Applier) CreateAtomicCutOverSentryTable() error {
|
|||
}
|
||||
tableName := this.migrationContext.GetOldTableName()
|
||||
|
||||
query := fmt.Sprintf(`create /* gh-ost */ table %s.%s (
|
||||
query := fmt.Sprintf(`
|
||||
create /* gh-ost */ table %s.%s (
|
||||
id int auto_increment primary key
|
||||
) engine=%s comment='%s'
|
||||
`,
|
||||
) engine=%s comment='%s'`,
|
||||
sql.EscapeName(this.migrationContext.DatabaseName),
|
||||
sql.EscapeName(tableName),
|
||||
this.migrationContext.TableEngine,
|
||||
|
@ -949,14 +950,14 @@ func (this *Applier) AtomicCutOverMagicLock(sessionIdChan chan int64, tableLocke
|
|||
}()
|
||||
|
||||
var sessionId int64
|
||||
if err := tx.QueryRow(`select connection_id()`).Scan(&sessionId); err != nil {
|
||||
if err := tx.QueryRow(`select /* gh-ost */ connection_id()`).Scan(&sessionId); err != nil {
|
||||
tableLocked <- err
|
||||
return err
|
||||
}
|
||||
sessionIdChan <- sessionId
|
||||
|
||||
lockResult := 0
|
||||
query := `select get_lock(?, 0)`
|
||||
query := `select /* gh-ost */ get_lock(?, 0)`
|
||||
lockName := this.GetSessionLockName(sessionId)
|
||||
this.migrationContext.Log.Infof("Grabbing voluntary lock: %s", lockName)
|
||||
if err := tx.QueryRow(query, lockName).Scan(&lockResult); err != nil || lockResult != 1 {
|
||||
|
@ -967,7 +968,7 @@ func (this *Applier) AtomicCutOverMagicLock(sessionIdChan chan int64, tableLocke
|
|||
|
||||
tableLockTimeoutSeconds := this.migrationContext.CutOverLockTimeoutSeconds * 2
|
||||
this.migrationContext.Log.Infof("Setting LOCK timeout as %d seconds", tableLockTimeoutSeconds)
|
||||
query = fmt.Sprintf(`set session lock_wait_timeout:=%d`, tableLockTimeoutSeconds)
|
||||
query = fmt.Sprintf(`set /* gh-ost */ session lock_wait_timeout:=%d`, tableLockTimeoutSeconds)
|
||||
if _, err := tx.Exec(query); err != nil {
|
||||
tableLocked <- err
|
||||
return err
|
||||
|
@ -1026,7 +1027,7 @@ func (this *Applier) AtomicCutOverMagicLock(sessionIdChan chan int64, tableLocke
|
|||
sql.EscapeName(this.migrationContext.DatabaseName),
|
||||
sql.EscapeName(this.migrationContext.GetOldTableName()),
|
||||
)
|
||||
query = `unlock tables`
|
||||
query = `unlock /* gh-ost */ tables`
|
||||
if _, err := tx.Exec(query); err != nil {
|
||||
tableUnlocked <- err
|
||||
return this.migrationContext.Log.Errore(err)
|
||||
|
@ -1048,13 +1049,13 @@ func (this *Applier) AtomicCutoverRename(sessionIdChan chan int64, tablesRenamed
|
|||
tablesRenamed <- fmt.Errorf("Unexpected error in AtomicCutoverRename(), injected to release blocking channel reads")
|
||||
}()
|
||||
var sessionId int64
|
||||
if err := tx.QueryRow(`select connection_id()`).Scan(&sessionId); err != nil {
|
||||
if err := tx.QueryRow(`select /* gh-ost */ connection_id()`).Scan(&sessionId); err != nil {
|
||||
return err
|
||||
}
|
||||
sessionIdChan <- sessionId
|
||||
|
||||
this.migrationContext.Log.Infof("Setting RENAME timeout as %d seconds", this.migrationContext.CutOverLockTimeoutSeconds)
|
||||
query := fmt.Sprintf(`set session lock_wait_timeout:=%d`, this.migrationContext.CutOverLockTimeoutSeconds)
|
||||
query := fmt.Sprintf(`set /* gh-ost */ session lock_wait_timeout:=%d`, this.migrationContext.CutOverLockTimeoutSeconds)
|
||||
if _, err := tx.Exec(query); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1080,7 +1081,7 @@ func (this *Applier) AtomicCutoverRename(sessionIdChan chan int64, tablesRenamed
|
|||
}
|
||||
|
||||
func (this *Applier) ShowStatusVariable(variableName string) (result int64, err error) {
|
||||
query := fmt.Sprintf(`show global status like '%s'`, variableName)
|
||||
query := fmt.Sprintf(`show /* gh-ost */ global status like '%s'`, variableName)
|
||||
if err := this.db.QueryRow(query).Scan(&variableName, &result); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -1150,7 +1151,7 @@ func (this *Applier) ApplyDMLEventQueries(dmlEvents [](*binlog.BinlogDMLEvent))
|
|||
return err
|
||||
}
|
||||
|
||||
sessionQuery := "SET SESSION time_zone = '+00:00'"
|
||||
sessionQuery := "SET /* gh-ost */ SESSION time_zone = '+00:00'"
|
||||
sessionQuery = fmt.Sprintf("%s, %s", sessionQuery, this.generateSqlModeQuery())
|
||||
|
||||
if _, err := tx.Exec(sessionQuery); err != nil {
|
||||
|
|
|
@ -114,13 +114,12 @@ func TestApplierBuildDMLEventQuery(t *testing.T) {
|
|||
res := applier.buildDMLEventQuery(binlogEvent)
|
||||
test.S(t).ExpectEquals(len(res), 1)
|
||||
test.S(t).ExpectNil(res[0].err)
|
||||
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
|
||||
`delete /* gh-ost `+"`test`.`_test_gho`"+` */
|
||||
from
|
||||
`+"`test`.`_test_gho`"+`
|
||||
where
|
||||
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`)
|
||||
|
||||
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query), `delete /* gh-ost `+"`test`.`_test_gho`"+` */
|
||||
from
|
||||
`+"`test`.`_test_gho`"+`
|
||||
where
|
||||
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`,
|
||||
)
|
||||
test.S(t).ExpectEquals(len(res[0].args), 2)
|
||||
test.S(t).ExpectEquals(res[0].args[0], 123456)
|
||||
test.S(t).ExpectEquals(res[0].args[1], 42)
|
||||
|
@ -136,11 +135,12 @@ func TestApplierBuildDMLEventQuery(t *testing.T) {
|
|||
test.S(t).ExpectEquals(len(res), 1)
|
||||
test.S(t).ExpectNil(res[0].err)
|
||||
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
|
||||
`replace /* gh-ost `+"`test`.`_test_gho`"+` */ into
|
||||
`+"`test`.`_test_gho`"+`
|
||||
`+"(`id`, `item_id`)"+`
|
||||
values
|
||||
(?, ?)`)
|
||||
`replace /* gh-ost `+"`test`.`_test_gho`"+` */
|
||||
into
|
||||
`+"`test`.`_test_gho`"+`
|
||||
`+"(`id`, `item_id`)"+`
|
||||
values
|
||||
(?, ?)`)
|
||||
test.S(t).ExpectEquals(len(res[0].args), 2)
|
||||
test.S(t).ExpectEquals(res[0].args[0], 123456)
|
||||
test.S(t).ExpectEquals(res[0].args[1], 42)
|
||||
|
@ -158,11 +158,11 @@ func TestApplierBuildDMLEventQuery(t *testing.T) {
|
|||
test.S(t).ExpectNil(res[0].err)
|
||||
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
|
||||
`update /* gh-ost `+"`test`.`_test_gho`"+` */
|
||||
`+"`test`.`_test_gho`"+`
|
||||
set
|
||||
`+"`id`"+`=?, `+"`item_id`"+`=?
|
||||
where
|
||||
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`)
|
||||
`+"`test`.`_test_gho`"+`
|
||||
set
|
||||
`+"`id`"+`=?, `+"`item_id`"+`=?
|
||||
where
|
||||
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`)
|
||||
test.S(t).ExpectEquals(len(res[0].args), 4)
|
||||
test.S(t).ExpectEquals(res[0].args[0], 123456)
|
||||
test.S(t).ExpectEquals(res[0].args[1], 42)
|
||||
|
|
|
@ -338,7 +338,7 @@ func (this *Inspector) applyBinlogFormat() error {
|
|||
|
||||
// validateBinlogs checks that binary log configuration is good to go
|
||||
func (this *Inspector) validateBinlogs() error {
|
||||
query := `select @@global.log_bin, @@global.binlog_format`
|
||||
query := `select /* gh-ost */ @@global.log_bin, @@global.binlog_format`
|
||||
var hasBinaryLogs bool
|
||||
if err := this.db.QueryRow(query).Scan(&hasBinaryLogs, &this.migrationContext.OriginalBinlogFormat); err != nil {
|
||||
return err
|
||||
|
@ -364,7 +364,7 @@ func (this *Inspector) validateBinlogs() error {
|
|||
}
|
||||
this.migrationContext.Log.Infof("%s has %s binlog_format. I will change it to ROW, and will NOT change it back, even in the event of failure.", this.connectionConfig.Key.String(), this.migrationContext.OriginalBinlogFormat)
|
||||
}
|
||||
query = `select @@global.binlog_row_image`
|
||||
query = `select /* gh-ost */ @@global.binlog_row_image`
|
||||
if err := this.db.QueryRow(query).Scan(&this.migrationContext.OriginalBinlogRowImage); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ func (this *Inspector) validateBinlogs() error {
|
|||
|
||||
// validateLogSlaveUpdates checks that binary log log_slave_updates is set. This test is not required when migrating on replica or when migrating directly on master
|
||||
func (this *Inspector) validateLogSlaveUpdates() error {
|
||||
query := `select @@global.log_slave_updates`
|
||||
query := `select /* gh-ost */ @@global.log_slave_updates`
|
||||
var logSlaveUpdates bool
|
||||
if err := this.db.QueryRow(query).Scan(&logSlaveUpdates); err != nil {
|
||||
return err
|
||||
|
@ -441,16 +441,18 @@ func (this *Inspector) validateTableForeignKeys(allowChildForeignKeys bool) erro
|
|||
return nil
|
||||
}
|
||||
query := `
|
||||
SELECT
|
||||
SELECT /* gh-ost */
|
||||
SUM(REFERENCED_TABLE_NAME IS NOT NULL AND TABLE_SCHEMA=? AND TABLE_NAME=?) as num_child_side_fk,
|
||||
SUM(REFERENCED_TABLE_NAME IS NOT NULL AND REFERENCED_TABLE_SCHEMA=? AND REFERENCED_TABLE_NAME=?) as num_parent_side_fk
|
||||
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
||||
FROM
|
||||
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
||||
WHERE
|
||||
REFERENCED_TABLE_NAME IS NOT NULL
|
||||
AND ((TABLE_SCHEMA=? AND TABLE_NAME=?)
|
||||
OR (REFERENCED_TABLE_SCHEMA=? AND REFERENCED_TABLE_NAME=?)
|
||||
)
|
||||
`
|
||||
REFERENCED_TABLE_NAME IS NOT NULL
|
||||
AND (
|
||||
(TABLE_SCHEMA=? AND TABLE_NAME=?)
|
||||
OR
|
||||
(REFERENCED_TABLE_SCHEMA=? AND REFERENCED_TABLE_NAME=?)
|
||||
)`
|
||||
numParentForeignKeys := 0
|
||||
numChildForeignKeys := 0
|
||||
err := sqlutils.QueryRowsMap(this.db, query, func(m sqlutils.RowMap) error {
|
||||
|
@ -487,12 +489,12 @@ func (this *Inspector) validateTableForeignKeys(allowChildForeignKeys bool) erro
|
|||
// validateTableTriggers makes sure no triggers exist on the migrated table
|
||||
func (this *Inspector) validateTableTriggers() error {
|
||||
query := `
|
||||
SELECT COUNT(*) AS num_triggers
|
||||
FROM INFORMATION_SCHEMA.TRIGGERS
|
||||
WHERE
|
||||
TRIGGER_SCHEMA=?
|
||||
AND EVENT_OBJECT_TABLE=?
|
||||
`
|
||||
SELECT /* gh-ost */ COUNT(*) AS num_triggers
|
||||
FROM
|
||||
INFORMATION_SCHEMA.TRIGGERS
|
||||
WHERE
|
||||
TRIGGER_SCHEMA=?
|
||||
AND EVENT_OBJECT_TABLE=?`
|
||||
numTriggers := 0
|
||||
err := sqlutils.QueryRowsMap(this.db, query, func(rowMap sqlutils.RowMap) error {
|
||||
numTriggers = rowMap.GetInt("num_triggers")
|
||||
|
@ -577,14 +579,12 @@ func (this *Inspector) CountTableRows(ctx context.Context) error {
|
|||
// applyColumnTypes
|
||||
func (this *Inspector) applyColumnTypes(databaseName, tableName string, columnsLists ...*sql.ColumnList) error {
|
||||
query := `
|
||||
select
|
||||
*
|
||||
from
|
||||
information_schema.columns
|
||||
where
|
||||
table_schema=?
|
||||
and table_name=?
|
||||
`
|
||||
select /* gh-ost */ *
|
||||
from
|
||||
information_schema.columns
|
||||
where
|
||||
table_schema=?
|
||||
and table_name=?`
|
||||
err := sqlutils.QueryRowsMap(this.db, query, func(m sqlutils.RowMap) error {
|
||||
columnName := m.GetString("COLUMN_NAME")
|
||||
columnType := m.GetString("COLUMN_TYPE")
|
||||
|
@ -633,14 +633,13 @@ func (this *Inspector) applyColumnTypes(databaseName, tableName string, columnsL
|
|||
// getAutoIncrementValue get's the original table's AUTO_INCREMENT value, if exists (0 value if not exists)
|
||||
func (this *Inspector) getAutoIncrementValue(tableName string) (autoIncrement uint64, err error) {
|
||||
query := `
|
||||
SELECT
|
||||
AUTO_INCREMENT
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
SELECT /* gh-ost */ AUTO_INCREMENT
|
||||
FROM
|
||||
INFORMATION_SCHEMA.TABLES
|
||||
WHERE
|
||||
TABLES.TABLE_SCHEMA = ?
|
||||
AND TABLES.TABLE_NAME = ?
|
||||
AND AUTO_INCREMENT IS NOT NULL
|
||||
`
|
||||
AND AUTO_INCREMENT IS NOT NULL`
|
||||
err = sqlutils.QueryRowsMap(this.db, query, func(m sqlutils.RowMap) error {
|
||||
autoIncrement = m.GetUint64("AUTO_INCREMENT")
|
||||
return nil
|
||||
|
@ -652,62 +651,67 @@ func (this *Inspector) getAutoIncrementValue(tableName string) (autoIncrement ui
|
|||
// candidate for chunking
|
||||
func (this *Inspector) getCandidateUniqueKeys(tableName string) (uniqueKeys [](*sql.UniqueKey), err error) {
|
||||
query := `
|
||||
SELECT
|
||||
COLUMNS.TABLE_SCHEMA,
|
||||
COLUMNS.TABLE_NAME,
|
||||
COLUMNS.COLUMN_NAME,
|
||||
UNIQUES.INDEX_NAME,
|
||||
UNIQUES.COLUMN_NAMES,
|
||||
UNIQUES.COUNT_COLUMN_IN_INDEX,
|
||||
COLUMNS.DATA_TYPE,
|
||||
COLUMNS.CHARACTER_SET_NAME,
|
||||
SELECT /* gh-ost */
|
||||
COLUMNS.TABLE_SCHEMA,
|
||||
COLUMNS.TABLE_NAME,
|
||||
COLUMNS.COLUMN_NAME,
|
||||
UNIQUES.INDEX_NAME,
|
||||
UNIQUES.COLUMN_NAMES,
|
||||
UNIQUES.COUNT_COLUMN_IN_INDEX,
|
||||
COLUMNS.DATA_TYPE,
|
||||
COLUMNS.CHARACTER_SET_NAME,
|
||||
LOCATE('auto_increment', EXTRA) > 0 as is_auto_increment,
|
||||
has_nullable
|
||||
FROM INFORMATION_SCHEMA.COLUMNS INNER JOIN (
|
||||
SELECT
|
||||
TABLE_SCHEMA,
|
||||
TABLE_NAME,
|
||||
INDEX_NAME,
|
||||
COUNT(*) AS COUNT_COLUMN_IN_INDEX,
|
||||
GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX ASC) AS COLUMN_NAMES,
|
||||
SUBSTRING_INDEX(GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX ASC), ',', 1) AS FIRST_COLUMN_NAME,
|
||||
SUM(NULLABLE='YES') > 0 AS has_nullable
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE
|
||||
has_nullable
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
INNER JOIN (
|
||||
SELECT
|
||||
TABLE_SCHEMA,
|
||||
TABLE_NAME,
|
||||
INDEX_NAME,
|
||||
COUNT(*) AS COUNT_COLUMN_IN_INDEX,
|
||||
GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX ASC) AS COLUMN_NAMES,
|
||||
SUBSTRING_INDEX(GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX ASC), ',', 1) AS FIRST_COLUMN_NAME,
|
||||
SUM(NULLABLE='YES') > 0 AS has_nullable
|
||||
FROM
|
||||
INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE
|
||||
NON_UNIQUE=0
|
||||
AND TABLE_SCHEMA = ?
|
||||
AND TABLE_NAME = ?
|
||||
GROUP BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME
|
||||
) AS UNIQUES
|
||||
ON (
|
||||
COLUMNS.COLUMN_NAME = UNIQUES.FIRST_COLUMN_NAME
|
||||
)
|
||||
WHERE
|
||||
COLUMNS.TABLE_SCHEMA = ?
|
||||
AND COLUMNS.TABLE_NAME = ?
|
||||
ORDER BY
|
||||
COLUMNS.TABLE_SCHEMA, COLUMNS.TABLE_NAME,
|
||||
CASE UNIQUES.INDEX_NAME
|
||||
WHEN 'PRIMARY' THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
CASE has_nullable
|
||||
WHEN 0 THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
CASE IFNULL(CHARACTER_SET_NAME, '')
|
||||
WHEN '' THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
CASE DATA_TYPE
|
||||
WHEN 'tinyint' THEN 0
|
||||
WHEN 'smallint' THEN 1
|
||||
WHEN 'int' THEN 2
|
||||
WHEN 'bigint' THEN 3
|
||||
ELSE 100
|
||||
END,
|
||||
COUNT_COLUMN_IN_INDEX
|
||||
`
|
||||
AND TABLE_NAME = ?
|
||||
GROUP BY
|
||||
TABLE_SCHEMA,
|
||||
TABLE_NAME,
|
||||
INDEX_NAME
|
||||
) AS UNIQUES
|
||||
ON (
|
||||
COLUMNS.COLUMN_NAME = UNIQUES.FIRST_COLUMN_NAME
|
||||
)
|
||||
WHERE
|
||||
COLUMNS.TABLE_SCHEMA = ?
|
||||
AND COLUMNS.TABLE_NAME = ?
|
||||
ORDER BY
|
||||
COLUMNS.TABLE_SCHEMA, COLUMNS.TABLE_NAME,
|
||||
CASE UNIQUES.INDEX_NAME
|
||||
WHEN 'PRIMARY' THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
CASE has_nullable
|
||||
WHEN 0 THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
CASE IFNULL(CHARACTER_SET_NAME, '')
|
||||
WHEN '' THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
CASE DATA_TYPE
|
||||
WHEN 'tinyint' THEN 0
|
||||
WHEN 'smallint' THEN 1
|
||||
WHEN 'int' THEN 2
|
||||
WHEN 'bigint' THEN 3
|
||||
ELSE 100
|
||||
END,
|
||||
COUNT_COLUMN_IN_INDEX`
|
||||
err = sqlutils.QueryRowsMap(this.db, query, func(m sqlutils.RowMap) error {
|
||||
uniqueKey := &sql.UniqueKey{
|
||||
Name: m.GetString("INDEX_NAME"),
|
||||
|
@ -797,8 +801,11 @@ func (this *Inspector) showCreateTable(tableName string) (createTableStatement s
|
|||
// readChangelogState reads changelog hints
|
||||
func (this *Inspector) readChangelogState(hint string) (string, error) {
|
||||
query := fmt.Sprintf(`
|
||||
select hint, value from %s.%s where hint = ? and id <= 255
|
||||
`,
|
||||
select /* gh-ost */ hint, value
|
||||
from
|
||||
%s.%s
|
||||
where
|
||||
hint = ? and id <= 255`,
|
||||
sql.EscapeName(this.migrationContext.DatabaseName),
|
||||
sql.EscapeName(this.migrationContext.GetChangelogTableName()),
|
||||
)
|
||||
|
|
|
@ -222,11 +222,20 @@ func BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName strin
|
|||
transactionalClause = "lock in share mode"
|
||||
}
|
||||
result = fmt.Sprintf(`
|
||||
insert /* gh-ost %s.%s */ ignore into %s.%s (%s)
|
||||
(select %s from %s.%s force index (%s)
|
||||
where (%s and %s) %s
|
||||
)
|
||||
`, databaseName, originalTableName, databaseName, ghostTableName, mappedSharedColumnsListing,
|
||||
insert /* gh-ost %s.%s */ ignore
|
||||
into
|
||||
%s.%s
|
||||
(%s)
|
||||
(
|
||||
select %s
|
||||
from
|
||||
%s.%s
|
||||
force index (%s)
|
||||
where
|
||||
(%s and %s)
|
||||
%s
|
||||
)`,
|
||||
databaseName, originalTableName, databaseName, ghostTableName, mappedSharedColumnsListing,
|
||||
sharedColumnsListing, databaseName, originalTableName, uniqueKey,
|
||||
rangeStartComparison, rangeEndComparison, transactionalClause)
|
||||
return result, explodedArgs, nil
|
||||
|
@ -274,16 +283,17 @@ func BuildUniqueKeyRangeEndPreparedQueryViaOffset(databaseName, tableName string
|
|||
}
|
||||
}
|
||||
result = fmt.Sprintf(`
|
||||
select /* gh-ost %s.%s %s */
|
||||
%s
|
||||
from
|
||||
%s.%s
|
||||
where %s and %s
|
||||
order by
|
||||
%s
|
||||
limit 1
|
||||
offset %d
|
||||
`, databaseName, tableName, hint,
|
||||
select /* gh-ost %s.%s %s */
|
||||
%s
|
||||
from
|
||||
%s.%s
|
||||
where
|
||||
%s and %s
|
||||
order by
|
||||
%s
|
||||
limit 1
|
||||
offset %d`,
|
||||
databaseName, tableName, hint,
|
||||
strings.Join(uniqueKeyColumnNames, ", "),
|
||||
databaseName, tableName,
|
||||
rangeStartComparison, rangeEndComparison,
|
||||
|
@ -329,21 +339,21 @@ func BuildUniqueKeyRangeEndPreparedQueryViaTemptable(databaseName, tableName str
|
|||
}
|
||||
}
|
||||
result = fmt.Sprintf(`
|
||||
select /* gh-ost %s.%s %s */ %s
|
||||
from (
|
||||
select
|
||||
%s
|
||||
from
|
||||
%s.%s
|
||||
where %s and %s
|
||||
order by
|
||||
%s
|
||||
limit %d
|
||||
) select_osc_chunk
|
||||
select /* gh-ost %s.%s %s */ %s
|
||||
from (
|
||||
select
|
||||
%s
|
||||
from
|
||||
%s.%s
|
||||
where
|
||||
%s and %s
|
||||
order by
|
||||
%s
|
||||
limit 1
|
||||
`, databaseName, tableName, hint, strings.Join(uniqueKeyColumnNames, ", "),
|
||||
limit %d) select_osc_chunk
|
||||
order by
|
||||
%s
|
||||
limit 1`,
|
||||
databaseName, tableName, hint, strings.Join(uniqueKeyColumnNames, ", "),
|
||||
strings.Join(uniqueKeyColumnNames, ", "), databaseName, tableName,
|
||||
rangeStartComparison, rangeEndComparison,
|
||||
strings.Join(uniqueKeyColumnAscending, ", "), chunkSize,
|
||||
|
@ -379,12 +389,12 @@ func buildUniqueKeyMinMaxValuesPreparedQuery(databaseName, tableName string, uni
|
|||
}
|
||||
query := fmt.Sprintf(`
|
||||
select /* gh-ost %s.%s */ %s
|
||||
from
|
||||
%s.%s
|
||||
force index (%s)
|
||||
order by %s
|
||||
limit 1
|
||||
`,
|
||||
from
|
||||
%s.%s
|
||||
force index (%s)
|
||||
order by
|
||||
%s
|
||||
limit 1`,
|
||||
databaseName, tableName, strings.Join(uniqueKeyColumnNames, ", "),
|
||||
databaseName, tableName, uniqueKey.Name,
|
||||
strings.Join(uniqueKeyColumnOrder, ", "),
|
||||
|
@ -411,12 +421,12 @@ func BuildDMLDeleteQuery(databaseName, tableName string, tableColumns, uniqueKey
|
|||
return result, uniqueKeyArgs, err
|
||||
}
|
||||
result = fmt.Sprintf(`
|
||||
delete /* gh-ost %s.%s */
|
||||
from
|
||||
%s.%s
|
||||
where
|
||||
%s
|
||||
`, databaseName, tableName,
|
||||
delete /* gh-ost %s.%s */
|
||||
from
|
||||
%s.%s
|
||||
where
|
||||
%s`,
|
||||
databaseName, tableName,
|
||||
databaseName, tableName,
|
||||
equalsComparison,
|
||||
)
|
||||
|
@ -449,12 +459,13 @@ func BuildDMLInsertQuery(databaseName, tableName string, tableColumns, sharedCol
|
|||
preparedValues := buildColumnsPreparedValues(mappedSharedColumns)
|
||||
|
||||
result = fmt.Sprintf(`
|
||||
replace /* gh-ost %s.%s */ into
|
||||
%s.%s
|
||||
(%s)
|
||||
values
|
||||
(%s)
|
||||
`, databaseName, tableName,
|
||||
replace /* gh-ost %s.%s */
|
||||
into
|
||||
%s.%s
|
||||
(%s)
|
||||
values
|
||||
(%s)`,
|
||||
databaseName, tableName,
|
||||
databaseName, tableName,
|
||||
strings.Join(mappedSharedColumnNames, ", "),
|
||||
strings.Join(preparedValues, ", "),
|
||||
|
@ -506,13 +517,13 @@ func BuildDMLUpdateQuery(databaseName, tableName string, tableColumns, sharedCol
|
|||
return "", sharedArgs, uniqueKeyArgs, err
|
||||
}
|
||||
result = fmt.Sprintf(`
|
||||
update /* gh-ost %s.%s */
|
||||
%s.%s
|
||||
set
|
||||
%s
|
||||
where
|
||||
%s
|
||||
`, databaseName, tableName,
|
||||
update /* gh-ost %s.%s */
|
||||
%s.%s
|
||||
set
|
||||
%s
|
||||
where
|
||||
%s`,
|
||||
databaseName, tableName,
|
||||
databaseName, tableName,
|
||||
setClause,
|
||||
equalsComparison,
|
||||
|
|
|
@ -175,11 +175,19 @@ func TestBuildRangeInsertQuery(t *testing.T) {
|
|||
query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true, false)
|
||||
test.S(t).ExpectNil(err)
|
||||
expected := `
|
||||
insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, position)
|
||||
(select id, name, position from mydb.tbl force index (PRIMARY)
|
||||
where (((id > @v1s) or ((id = @v1s))) and ((id < @v1e) or ((id = @v1e))))
|
||||
)
|
||||
`
|
||||
insert /* gh-ost mydb.tbl */ ignore
|
||||
into
|
||||
mydb.ghost
|
||||
(id, name, position)
|
||||
(
|
||||
select id, name, position
|
||||
from
|
||||
mydb.tbl
|
||||
force index (PRIMARY)
|
||||
where
|
||||
(((id > @v1s) or ((id = @v1s)))
|
||||
and ((id < @v1e) or ((id = @v1e))))
|
||||
)`
|
||||
test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
|
||||
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 103, 103}))
|
||||
}
|
||||
|
@ -194,11 +202,25 @@ func TestBuildRangeInsertQuery(t *testing.T) {
|
|||
query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true, false)
|
||||
test.S(t).ExpectNil(err)
|
||||
expected := `
|
||||
insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, position)
|
||||
(select id, name, position from mydb.tbl force index (name_position_uidx)
|
||||
where (((name > @v1s) or (((name = @v1s)) AND (position > @v2s)) or ((name = @v1s) and (position = @v2s))) and ((name < @v1e) or (((name = @v1e)) AND (position < @v2e)) or ((name = @v1e) and (position = @v2e))))
|
||||
)
|
||||
`
|
||||
insert /* gh-ost mydb.tbl */ ignore
|
||||
into
|
||||
mydb.ghost
|
||||
(id, name, position)
|
||||
(
|
||||
select id, name, position
|
||||
from
|
||||
mydb.tbl
|
||||
force index (name_position_uidx)
|
||||
where
|
||||
(((name > @v1s) or (((name = @v1s))
|
||||
AND (position > @v2s))
|
||||
or ((name = @v1s)
|
||||
and (position = @v2s)))
|
||||
and ((name < @v1e)
|
||||
or (((name = @v1e))
|
||||
AND (position < @v2e))
|
||||
or ((name = @v1e) and (position = @v2e))))
|
||||
)`
|
||||
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}))
|
||||
}
|
||||
|
@ -221,11 +243,20 @@ func TestBuildRangeInsertQueryRenameMap(t *testing.T) {
|
|||
query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, mappedSharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true, false)
|
||||
test.S(t).ExpectNil(err)
|
||||
expected := `
|
||||
insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, location)
|
||||
(select id, name, position from mydb.tbl force index (PRIMARY)
|
||||
where (((id > @v1s) or ((id = @v1s))) and ((id < @v1e) or ((id = @v1e))))
|
||||
)
|
||||
`
|
||||
insert /* gh-ost mydb.tbl */ ignore
|
||||
into
|
||||
mydb.ghost
|
||||
(id, name, location)
|
||||
(
|
||||
select id, name, position
|
||||
from
|
||||
mydb.tbl
|
||||
force index (PRIMARY)
|
||||
where
|
||||
(((id > @v1s) or ((id = @v1s)))
|
||||
and
|
||||
((id < @v1e) or ((id = @v1e))))
|
||||
)`
|
||||
test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
|
||||
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 103, 103}))
|
||||
}
|
||||
|
@ -240,11 +271,21 @@ func TestBuildRangeInsertQueryRenameMap(t *testing.T) {
|
|||
query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, mappedSharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true, false)
|
||||
test.S(t).ExpectNil(err)
|
||||
expected := `
|
||||
insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, location)
|
||||
(select id, name, position from mydb.tbl force index (name_position_uidx)
|
||||
where (((name > @v1s) or (((name = @v1s)) AND (position > @v2s)) or ((name = @v1s) and (position = @v2s))) and ((name < @v1e) or (((name = @v1e)) AND (position < @v2e)) or ((name = @v1e) and (position = @v2e))))
|
||||
)
|
||||
`
|
||||
insert /* gh-ost mydb.tbl */ ignore
|
||||
into
|
||||
mydb.ghost
|
||||
(id, name, location)
|
||||
(
|
||||
select id, name, position
|
||||
from
|
||||
mydb.tbl
|
||||
force index (name_position_uidx)
|
||||
where
|
||||
(((name > @v1s) or (((name = @v1s))
|
||||
AND (position > @v2s)) or ((name = @v1s) and (position = @v2s)))
|
||||
and ((name < @v1e) or (((name = @v1e)) AND (position < @v2e))
|
||||
or ((name = @v1e) and (position = @v2e))))
|
||||
)`
|
||||
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}))
|
||||
}
|
||||
|
@ -264,11 +305,18 @@ func TestBuildRangeInsertPreparedQuery(t *testing.T) {
|
|||
query, explodedArgs, err := BuildRangeInsertPreparedQuery(databaseName, originalTableName, ghostTableName, sharedColumns, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartArgs, rangeEndArgs, true, true)
|
||||
test.S(t).ExpectNil(err)
|
||||
expected := `
|
||||
insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, position)
|
||||
(select id, name, position from mydb.tbl force index (name_position_uidx)
|
||||
where (((name > ?) or (((name = ?)) AND (position > ?)) or ((name = ?) and (position = ?))) and ((name < ?) or (((name = ?)) AND (position < ?)) or ((name = ?) and (position = ?))))
|
||||
lock in share mode )
|
||||
`
|
||||
insert /* gh-ost mydb.tbl */ ignore
|
||||
into
|
||||
mydb.ghost
|
||||
(id, name, position)
|
||||
(
|
||||
select id, name, position
|
||||
from
|
||||
mydb.tbl
|
||||
force index (name_position_uidx)
|
||||
where (((name > ?) or (((name = ?)) AND (position > ?)) or ((name = ?) and (position = ?))) and ((name < ?) or (((name = ?)) AND (position < ?)) or ((name = ?) and (position = ?))))
|
||||
lock in share mode
|
||||
)`
|
||||
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}))
|
||||
}
|
||||
|
@ -286,21 +334,19 @@ func TestBuildUniqueKeyRangeEndPreparedQuery(t *testing.T) {
|
|||
query, explodedArgs, err := BuildUniqueKeyRangeEndPreparedQueryViaTemptable(databaseName, originalTableName, uniqueKeyColumns, rangeStartArgs, rangeEndArgs, chunkSize, false, "test")
|
||||
test.S(t).ExpectNil(err)
|
||||
expected := `
|
||||
select /* gh-ost mydb.tbl test */ name, position
|
||||
from (
|
||||
select
|
||||
name, position
|
||||
from
|
||||
mydb.tbl
|
||||
where ((name > ?) or (((name = ?)) AND (position > ?))) and ((name < ?) or (((name = ?)) AND (position < ?)) or ((name = ?) and (position = ?)))
|
||||
order by
|
||||
name asc, position asc
|
||||
limit 500
|
||||
) select_osc_chunk
|
||||
select /* gh-ost mydb.tbl test */ name, position
|
||||
from (
|
||||
select
|
||||
name, position
|
||||
from
|
||||
mydb.tbl
|
||||
where ((name > ?) or (((name = ?)) AND (position > ?))) and ((name < ?) or (((name = ?)) AND (position < ?)) or ((name = ?) and (position = ?)))
|
||||
order by
|
||||
name desc, position desc
|
||||
limit 1
|
||||
`
|
||||
name asc, position asc
|
||||
limit 500) select_osc_chunk
|
||||
order by
|
||||
name desc, position desc
|
||||
limit 1`
|
||||
test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
|
||||
test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 103, 103, 117, 103, 117}))
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче