Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions localtests/move-tables/multiple-two-with-hooks/create.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
-- Two tables with different schemas, primary-key types, and row counts. This
-- exercises the multi-table move-tables path (§2.1-2.4): per-table runtime
-- state, per-table query builders, interleaved row copy where the tables finish
-- at different times, and a single atomic multi-table RENAME at cutover.

drop table if exists gh_ost_test;
create table gh_ost_test (
id bigint(20) NOT NULL AUTO_INCREMENT,
column1 int(11) NOT NULL,
column2 smallint(5) unsigned NOT NULL,
column3 mediumint(8) unsigned NOT NULL,
column4 tinyint(3) unsigned NOT NULL,
column5 int(11) NOT NULL,
column6 int(11) NOT NULL,
PRIMARY KEY (id),
KEY c12_ix (column1, column2)
) auto_increment=1;

insert into gh_ost_test values
(NULL, 1001, 100, 500000, 10, 1700000001, 1700000002),
(NULL, 1002, 200, 600000, 20, 1700000003, 1700000004),
(NULL, 1003, 300, 700000, 30, 1700000005, 1700000006),
(NULL, 1004, 400, 800000, 40, 1700000007, 1700000008),
(NULL, 1005, 500, 900000, 50, 1700000009, 1700000010),
(NULL, 1006, 600, 1000000, 60, 1700000011, 1700000012),
(NULL, 1007, 700, 1100000, 70, 1700000013, 1700000014),
(NULL, 1008, 800, 1200000, 80, 1700000015, 1700000016),
(NULL, 1009, 900, 1300000, 90, 1700000017, 1700000018),
(NULL, 1010, 1000, 1400000, 100, 1700000019, 1700000020),
(NULL, 1011, 1100, 1500000, 110, 1700000021, 1700000022),
(NULL, 1012, 1200, 1600000, 120, 1700000023, 1700000024),
(NULL, 1013, 1300, 1700000, 130, 1700000025, 1700000026),
(NULL, 1014, 1400, 1800000, 140, 1700000027, 1700000028),
(NULL, 1015, 1500, 1900000, 150, 1700000029, 1700000030),
(NULL, 1016, 1600, 2000000, 160, 1700000031, 1700000032),
(NULL, 1017, 1700, 2100000, 170, 1700000033, 1700000034),
(NULL, 1018, 1800, 2200000, 180, 1700000035, 1700000036),
(NULL, 1019, 1900, 2300000, 190, 1700000037, 1700000038),
(NULL, 1020, 2000, 2400000, 200, 1700000039, 1700000040),
(NULL, 1021, 2100, 2500000, 210, 1700000041, 1700000042),
(NULL, 1022, 2200, 2600000, 220, 1700000043, 1700000044),
(NULL, 1023, 2300, 2700000, 230, 1700000045, 1700000046),
(NULL, 1024, 2400, 2800000, 240, 1700000047, 1700000048),
(NULL, 1025, 2500, 2900000, 250, 1700000049, 1700000050);

drop table if exists gh_ost_test_other;
create table gh_ost_test_other (
uid int(11) NOT NULL,
name varchar(64) NOT NULL,
amount decimal(10,2) NOT NULL,
created_at datetime NOT NULL,
PRIMARY KEY (uid),
UNIQUE KEY name_uq (name)
);

insert into gh_ost_test_other values
(1, 'alpha', 10.50, '2024-01-01 10:00:00'),
(2, 'bravo', 20.75, '2024-01-02 11:00:00'),
(3, 'charlie', 30.00, '2024-01-03 12:00:00'),
(4, 'delta', 40.25, '2024-01-04 13:00:00'),
(5, 'echo', 50.50, '2024-01-05 14:00:00'),
(6, 'foxtrot', 60.75, '2024-01-06 15:00:00'),
(7, 'golf', 70.00, '2024-01-07 16:00:00'),
(8, 'hotel', 80.25, '2024-01-08 17:00:00'),
(9, 'india', 90.50, '2024-01-09 18:00:00'),
(10, 'juliet', 100.75, '2024-01-10 19:00:00'),
(11, 'kilo', 110.00, '2024-01-11 20:00:00'),
(12, 'lima', 120.25, '2024-01-12 21:00:00');
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/util.sh"

# dump environment variables on dirty exit
trap '[[ $? -eq 0 ]] || dump_env' EXIT

set -e

assert_common_envs

# touch file to mark completion of on-before-cut-over hook
touch /tmp/gh-ost-hooks/on-before-cut-over
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/util.sh"

# dump environment variables on dirty exit
trap '[[ $? -eq 0 ]] || dump_env' EXIT

set -e

assert_common_envs

# touch file to mark completion of on-row-copy-complete hook
touch /tmp/gh-ost-hooks/on-row-copy-complete
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/util.sh"

# dump environment variables on dirty exit
trap '[[ $? -eq 0 ]] || dump_env' EXIT

set -e

assert_common_envs

assert_env_present "GH_OST_DRAIN_GTID"

# touch file to mark completion of on-success hook
touch /tmp/gh-ost-hooks/on-success
80 changes: 80 additions & 0 deletions localtests/move-tables/multiple-two-with-hooks/hooks/util.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#/bin/bash

assert_env_equal() {
env_name=$1
expected=$2

if [ "${!env_name}" != "${expected}" ]; then
echo "ERROR: Expected '${expected}' for ${env_name}, but got '${!env_name}'"
exit 1
fi
}

assert_env_present() {
env_name=$1

echo "checking '${env_name}=${!env_name}'"
if [[ -z "${!env_name}" ]]; then
echo "ERROR: Expected '${env_name}' to be set but not present"
exit 1
fi
}

# Assert a table-list env var holds ONLY comma-separated table names, with no
# schema/database prefix. gh-ost must expose bare table names (e.g.
# "gh_ost_test,gh_ost_test_other"), never schema-qualified ones (e.g.
# "test.gh_ost_test,test.gh_ost_test_other"). A '.' in any element signals a
# leaked schema prefix — the db-infra-scripts hooks build `db`.`table` grants
# themselves and would double-qualify if gh-ost passed a prefix.
assert_no_schema_prefix() {
env_name=$1
value="${!env_name}"

echo "checking '${env_name}' has no schema prefix: '${value}'"

local IFS=','
for element in ${value}; do
if [[ "${element}" == *.* ]]; then
echo "ERROR: ${env_name} element '${element}' is schema-qualified; expected a bare table name"
exit 1
fi
done
}

# Assert the environment contract gh-ost exposes to hooks for a multi-table move.
# The table-name variables are comma-joined lists (in tables.txt order), with the
# rollback handles being the per-table `_<table>_del` names produced by the atomic
# cutover RENAME. This mirrors go/logic/hooks.go:applyEnvironmentVariables and is
# the exact contract the db-infra-scripts move-tables hooks rely on (a regression
# here is what caused the per-table GRANT bug).
assert_common_envs() {
assert_env_present "GH_OST_TARGET_HOST"

assert_env_equal "GH_OST_TARGET_DATABASE_NAME" "test"
assert_env_equal "GH_OST_TABLE_NAME" "gh_ost_test,gh_ost_test_other"
assert_env_equal "GH_OST_GHOST_TABLE_NAME" "gh_ost_test,gh_ost_test_other"
assert_env_equal "GH_OST_TARGET_TABLE_NAME" "gh_ost_test,gh_ost_test_other"
assert_env_equal "GH_OST_OLD_TABLE_NAME" "_gh_ost_test_del,_gh_ost_test_other_del"
assert_env_equal "GH_OST_TABLES" "gh_ost_test,gh_ost_test_other"
assert_env_equal "GH_OST_MOVE_TABLES" "true"
assert_env_equal "GH_OST_REVERT" "false"

# The table lists must be bare, comma-separated table names — never
# schema-qualified (the database is carried separately in
# GH_OST_TARGET_DATABASE_NAME).
assert_no_schema_prefix "GH_OST_TABLE_NAME"
assert_no_schema_prefix "GH_OST_GHOST_TABLE_NAME"
assert_no_schema_prefix "GH_OST_TARGET_TABLE_NAME"
assert_no_schema_prefix "GH_OST_OLD_TABLE_NAME"
assert_no_schema_prefix "GH_OST_TABLES"
}

dump_env() {
echo "-----------------------------------------------------"
echo "----------------- ENVIRONS --------------------------"
echo "-----------------------------------------------------"
env | grep "GH_OST_"
echo "-----------------------------------------------------"
echo "-----------------------------------------------------"
echo "-----------------------------------------------------"
}
2 changes: 2 additions & 0 deletions localtests/move-tables/multiple-two-with-hooks/tables.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
gh_ost_test
gh_ost_test_other
71 changes: 71 additions & 0 deletions localtests/move-tables/multiple-two-with-hooks/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@

#!/bin/bash
# Custom test:
# Executes a MULTI-table move-tables migration with custom hooks
# (on-row-copy-complete, on-before-cut-over, on-success). The hooks assert the
# environment-variable contract gh-ost exposes for multi-table moves — most
# importantly that GH_OST_TABLE_NAME (and the ghost/target/old/tables vars) are
# comma-joined lists. This is the exact contract the db-infra-scripts
# move-tables ACL hooks depend on; getting it wrong caused a per-table GRANT
# bug that a single-table test could not catch.

database=test

# Build gh-ost command from scratch using framework function
build_binary

######################################################################################################
### Run gh-ost with custom hooks enabled
######################################################################################################

echo "Running gh-ost (multi-table) with custom hooks..."

# ensure hook files are executable
chmod +x $tests_path/$test_name/hooks/*

# clean up any existing test hook files
rm -rf /tmp/gh-ost-hooks/
mkdir -p /tmp/gh-ost-hooks/

# Build the gh-ost command using the framework function (moves every table listed
# in tables.txt, which test_single loaded into tables_to_migrate).
build_ghost_command
cmd="$cmd --hooks-path=$tests_path/$test_name/hooks"

# queue up removal of the postpone cutover flag, otherwise gh-ost hangs on the cutover
(
sleep 2;
echo "Sending unpostpone cutover"
rm $postpone_cutover_flag_file &> /dev/null;
) &

# Run the gh-ost command
echo_dot
echo > $test_logfile
bash -c "$cmd" >>$test_logfile 2>&1
ghost_result=$?

if [ $ghost_result -ne 0 ]; then
echo "ERROR: gh-ost failed unexpectedly."
return 1
fi

echo "gh-ost move-tables succeeded!"

echo -e "\n\n\n\n\n"


######################################################################################################
### Validate hook status
######################################################################################################

echo "Validating hook status after execution..."

for expected in on-row-copy-complete on-before-cut-over on-success; do
if [ ! -f "/tmp/gh-ost-hooks/$expected" ]; then
echo "ERROR: Expected test hook file '/tmp/gh-ost-hooks/$expected' was not found."
return 1
fi
done

echo "Hook status validated successfully."
Loading