From 31d763d5b9e960746a6b0a1f8b1ec07482027222 Mon Sep 17 00:00:00 2001 From: zgxme Date: Tue, 30 Jun 2026 15:40:38 +0800 Subject: [PATCH 1/4] fix: support catalog-qualified benchmark databases --- engines/doris_engine.sh | 82 ++++++++++++++++++++++--------------- engines/starrocks_engine.sh | 61 +++++++++++++++++++++++---- 2 files changed, 100 insertions(+), 43 deletions(-) diff --git a/engines/doris_engine.sh b/engines/doris_engine.sh index 1b690f9..f2646c1 100644 --- a/engines/doris_engine.sh +++ b/engines/doris_engine.sh @@ -21,6 +21,28 @@ source "$(dirname "${BASH_SOURCE[0]}")/../lib/jdbc_utils.sh" BE_HOSTS_ARR=() +doris_qualified_db() { + local db_name="$1" + + if [ -n "${catalog:-}" ] && [ -n "$db_name" ] && [[ "$db_name" != *.* ]]; then + printf '%s.%s\n' "$catalog" "$db_name" + else + printf '%s\n' "$db_name" + fi +} + +doris_qualified_table() { + local table_name="$1" + local db_name + + db_name="$(doris_qualified_db "${db:-}")" + if [[ "$table_name" != *.* ]] && [ -n "$db_name" ]; then + printf '%s.%s\n' "$db_name" "$table_name" + else + printf '%s\n' "$table_name" + fi +} + any_clear_cache_enabled() { [[ "${clear_file_cache:-false}" == "true" \ || "${clear_sys_page_cache:-false}" == "true" ]] @@ -204,6 +226,8 @@ engine_init() { # 2. Execute a SQL file using mysql client engine_run_sql_file() { local sql_file="$1" + local apply_session="${2:-true}" + local db_name local error_file="" local status=0 @@ -214,6 +238,14 @@ engine_run_sql_file() { # Set password environment variable for mysql export MYSQL_PWD="${password:-}" + db_name="${db:-}" + # DDL setup passes apply_session=false and may create/drop the catalog itself, + # so do not select catalog.db before the catalog exists. + if [ "$apply_session" != "false" ]; then + db_name="$(doris_qualified_db "$db_name")" + fi + local args=(-h"$fe_host" -P"$fe_query_port" -u"$user") + [ -n "$db_name" ] && args+=(-D"$db_name") error_file="$(mktemp "${TMPDIR:-/tmp}/doris_mysql_stderr.XXXXXX")" || { echo "ERROR: Failed to create temporary stderr file" >&2 @@ -221,13 +253,7 @@ engine_run_sql_file() { } # Execute the SQL file - if mysql \ - -h"$fe_host" \ - -P"$fe_query_port" \ - -u"$user" \ - -D"$db" \ - 2>"$error_file" \ - < "$sql_file"; then + if mysql "${args[@]}" 2>"$error_file" < "$sql_file"; then rm -f "$error_file" return 0 else @@ -259,7 +285,7 @@ engine_run_sql() { # Build mysql command arguments local args=(-h"$fe_host" -P"$fe_query_port" -u"$user") - [ -n "${catalog:-}" ] && [ -n "$db" ] && db="${catalog}.${db}" + db="$(doris_qualified_db "$db")" [ -n "$db" ] && args+=(-D"$db") local mysql_sql="$sql_statement" @@ -309,9 +335,7 @@ engine_list_tables() { local db_name="$1" local args=(-h"$fe_host" -P"$fe_query_port" -u"$user" -N -s) - if [ -n "${catalog:-}" ]; then - db_name="${catalog}.${db_name}" - fi + db_name="$(doris_qualified_db "$db_name")" [ -n "$db_name" ] && args+=(-D"$db_name") export MYSQL_PWD="${password:-}" @@ -323,9 +347,7 @@ engine_drop_stats() { local table="$2" local args=(-h"$fe_host" -P"$fe_query_port" -u"$user") - if [ -n "${catalog:-}" ]; then - db_name="${catalog}.${db_name}" - fi + db_name="$(doris_qualified_db "$db_name")" [ -n "$db_name" ] && args+=(-D"$db_name") export MYSQL_PWD="${password:-}" @@ -339,9 +361,7 @@ engine_analyze_table() { local args=(-h"$fe_host" -P"$fe_query_port" -u"$user") local sql="" - if [ -n "${catalog:-}" ]; then - db_name="${catalog}.${db_name}" - fi + db_name="$(doris_qualified_db "$db_name")" [ -n "$db_name" ] && args+=(-D"$db_name") case "${analyze_type}" in @@ -369,9 +389,7 @@ engine_show_column_stats() { local table="$2" local args=(-h"$fe_host" -P"$fe_query_port" -u"$user") - if [ -n "${catalog:-}" ]; then - db_name="${catalog}.${db_name}" - fi + db_name="$(doris_qualified_db "$db_name")" [ -n "$db_name" ] && args+=(-D"$db_name") export MYSQL_PWD="${password:-}" @@ -384,18 +402,10 @@ engine_get_table_rows() { local port="${fe_query_port:-9030}" local sys_user="${user:-root}" local current_db="${db:-}" - local qualified_table="$table" + local qualified_table - if [ -n "${catalog:-}" ] && [ -n "$current_db" ]; then - current_db="${catalog}.${current_db}" - fi - - # Support bare table names in benchmark.yaml tables config when a catalog - # is configured, while still allowing callers to pass db.table or - # catalog.db.table explicitly. - if [[ "$qualified_table" != *.* ]] && [ -n "${catalog:-}" ] && [ -n "${db:-}" ]; then - qualified_table="${catalog}.${db}.${qualified_table}" - fi + current_db="$(doris_qualified_db "$current_db")" + qualified_table="$(doris_qualified_table "$table")" # Do not use `export MYSQL_PWD` to avoid environment pollution MYSQL_PWD="${password:-}" mysql -h"${host}" -P"${port}" -u"${sys_user}" "${current_db}" \ @@ -688,7 +698,9 @@ run_clear_cache_actions() { engine_get_jdbc_datasource() { # Escape any special characters in the password local escaped_password + local jdbc_db escaped_password=$(xml_escape "${password:-}") + jdbc_db="$(doris_qualified_db "${db:-}")" cat << EOF @@ -697,7 +709,7 @@ engine_get_jdbc_datasource() { 5000 ${ENGINE_TYPE:-Doris} - jdbc:mysql://${fe_host}:${fe_query_port}/${db} + jdbc:mysql://${fe_host}:${fe_query_port}/${jdbc_db} com.mysql.cj.jdbc.Driver true ${escaped_password} @@ -754,7 +766,7 @@ engine_get_plan() { local sql_statement="$2" export MYSQL_PWD="${password:-}" local args=(-h"$fe_host" -P"$fe_query_port" -u"$user" -N -s) - [ -n "${catalog:-}" ] && db_name="${catalog}.${db_name}" + db_name="$(doris_qualified_db "$db_name")" [ -n "$db_name" ] && args+=(-D"$db_name") mysql "${args[@]}" -e "explain memo plan ${sql_statement}" 2>/dev/null || true } @@ -763,7 +775,9 @@ engine_get_plan() { engine_get_version() { export MYSQL_PWD="${password:-}" local args=(-h"$fe_host" -P"$fe_query_port" -u"$user") - [ -n "${db:-}" ] && args+=(-D"$db") + local db_name + db_name="$(doris_qualified_db "${db:-}")" + [ -n "$db_name" ] && args+=(-D"$db_name") local version version=$(mysql "${args[@]}" -N -s -e "SHOW VARIABLES LIKE 'version_comment';" 2>/dev/null | cut -f2- || true) diff --git a/engines/starrocks_engine.sh b/engines/starrocks_engine.sh index 8c1251a..d63f618 100644 --- a/engines/starrocks_engine.sh +++ b/engines/starrocks_engine.sh @@ -16,6 +16,28 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/interface.sh" +starrocks_qualified_db() { + local db_name="$1" + + if [ -n "${catalog:-}" ] && [ -n "$db_name" ] && [[ "$db_name" != *.* ]]; then + printf '%s.%s\n' "$catalog" "$db_name" + else + printf '%s\n' "$db_name" + fi +} + +starrocks_qualified_table() { + local table_name="$1" + local db_name + + db_name="$(starrocks_qualified_db "${db:-}")" + if [[ "$table_name" != *.* ]] && [ -n "$db_name" ]; then + printf '%s.%s\n' "$db_name" "$table_name" + else + printf '%s\n' "$table_name" + fi +} + # 1. Initialize and check StarRocks dependencies engine_init() { echo "Initializing StarRocks engine..." @@ -93,6 +115,8 @@ init_mysql_jdbc_driver() { # 2. Execute a SQL file using mysql client engine_run_sql_file() { local sql_file="$1" + local apply_session="${2:-true}" + local db_name if [ ! -f "$sql_file" ]; then echo "ERROR: SQL file not found: $sql_file" >&2 @@ -101,14 +125,17 @@ engine_run_sql_file() { # Set password environment variable for mysql export MYSQL_PWD="${password:-}" + db_name="${db:-}" + # DDL setup passes apply_session=false and may create/drop the catalog itself, + # so do not select catalog.db before the catalog exists. + if [ "$apply_session" != "false" ]; then + db_name="$(starrocks_qualified_db "$db_name")" + fi + local args=(-h"$fe_host" -P"$fe_query_port" -u"$user") + [ -n "$db_name" ] && args+=(-D"$db_name") # Execute the SQL file - if mysql \ - -h"$fe_host" \ - -P"$fe_query_port" \ - -u"$user" \ - -D"$db" \ - < "$sql_file"; then + if mysql "${args[@]}" < "$sql_file"; then return 0 else echo "ERROR: Failed to execute SQL file: $sql_file" >&2 @@ -132,6 +159,7 @@ engine_run_sql() { # Build mysql command arguments local args=(-h"$fe_host" -P"$fe_query_port" -u"$user") + db="$(starrocks_qualified_db "$db")" [ -n "$db" ] && args+=(-D"$db") local mysql_sql="$sql_statement" @@ -164,10 +192,14 @@ engine_get_table_rows() { local port="${fe_query_port:-9030}" local sys_user="${user:-root}" local current_db="${db:-}" + local qualified_table + + current_db="$(starrocks_qualified_db "$current_db")" + qualified_table="$(starrocks_qualified_table "$table")" local count count="$(MYSQL_PWD="${password:-}" mysql -h"${host}" -P"${port}" -u"${sys_user}" -D"${current_db}" \ - -N -s -e "SELECT COUNT(*) FROM ${table};" 2>/dev/null || true)" + -N -s -e "SELECT COUNT(*) FROM ${qualified_table};" 2>/dev/null || true)" count="${count%%$'\n'*}" count="${count//$'\r'/}" @@ -216,6 +248,8 @@ engine_set_auto_analyze() { engine_list_tables() { local db_name="$1" + db_name="$(starrocks_qualified_db "$db_name")" + export MYSQL_PWD="${password:-}" mysql -h"$fe_host" -P"$fe_query_port" -u"$user" -D"$db_name" -N -s -e "SHOW TABLES;" 2>/dev/null } @@ -223,6 +257,8 @@ engine_list_tables() { engine_drop_stats() { local db_name="$1" local table="$2" + db_name="$(starrocks_qualified_db "$db_name")" + export MYSQL_PWD="${password:-}" mysql -h"$fe_host" -P"$fe_query_port" -u"$user" -D"$db_name" -e "DROP STATS ${table};" >/dev/null 2>&1 } @@ -233,6 +269,8 @@ engine_analyze_table() { local analyze_type="$3" local sql="" + db_name="$(starrocks_qualified_db "$db_name")" + case "${analyze_type}" in analyze_full) sql="analyze full table ${table} with sync mode" @@ -301,6 +339,7 @@ engine_get_plan() { local sql_statement="$2" export MYSQL_PWD="${password:-}" local args=(-h"$fe_host" -P"$fe_query_port" -u"$user" -N -s) + db_name="$(starrocks_qualified_db "$db_name")" [ -n "$db_name" ] && args+=(-D"$db_name") mysql "${args[@]}" -e "EXPLAIN VERBOSE ${sql_statement}" 2>/dev/null || true } @@ -309,7 +348,9 @@ engine_get_plan() { engine_get_jdbc_datasource() { # Escape any special characters in the password local escaped_password + local jdbc_db escaped_password=$(xml_escape "${password:-}") + jdbc_db="$(starrocks_qualified_db "${db:-}")" cat << EOF @@ -318,7 +359,7 @@ engine_get_jdbc_datasource() { 5000 Starrocks - jdbc:mysql://${fe_host}:${fe_query_port}/${db} + jdbc:mysql://${fe_host}:${fe_query_port}/${jdbc_db} com.mysql.cj.jdbc.Driver true ${escaped_password} @@ -340,7 +381,9 @@ engine_get_jdbc_sampler_name() { engine_get_version() { export MYSQL_PWD="${password:-}" local args=(-h"$fe_host" -P"$fe_query_port" -u"$user") - [ -n "${db:-}" ] && args+=(-D"$db") + local db_name + db_name="$(starrocks_qualified_db "${db:-}")" + [ -n "$db_name" ] && args+=(-D"$db_name") local version version=$(mysql "${args[@]}" -N -s -e "SHOW VARIABLES LIKE 'version_comment';" 2>/dev/null | cut -f2- || true) From 32a65426093181615317687ef75e803d281cf0b7 Mon Sep 17 00:00:00 2001 From: zgxme Date: Tue, 30 Jun 2026 17:02:27 +0800 Subject: [PATCH 2/4] fix: run benchmark SQL through mysql stdin --- engines/doris_engine.sh | 13 ++++++++++--- engines/starrocks_engine.sh | 24 +++++++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/engines/doris_engine.sh b/engines/doris_engine.sh index f2646c1..15b96f9 100644 --- a/engines/doris_engine.sh +++ b/engines/doris_engine.sh @@ -273,6 +273,7 @@ engine_run_sql() { local sql_statement="$2" local capture_last_query_id="${3:-true}" local error_file="" + local sql_file="" local status=0 if [ -z "$sql_statement" ]; then @@ -301,8 +302,14 @@ engine_run_sql() { echo "ERROR: Failed to create temporary stderr file" >&2 return 1 } - if output=$(mysql "${args[@]}" --batch --skip-column-names \ - -e "$mysql_sql" 2>"$error_file"); then + sql_file="$(mktemp "${TMPDIR:-/tmp}/doris_mysql_sql.XXXXXX")" || { + echo "ERROR: Failed to create temporary SQL file" >&2 + rm -f "$error_file" + return 1 + } + printf '%s\n' "$mysql_sql" > "$sql_file" + if output=$(mysql "${args[@]}" --batch --skip-column-names < "$sql_file" 2>"$error_file"); then + rm -f "$sql_file" rm -f "$error_file" if [ "$capture_last_query_id" = "true" ]; then # The last non-empty line of stdout is the query ID. @@ -315,7 +322,7 @@ engine_run_sql() { if [ -s "$error_file" ]; then cat "$error_file" >&2 fi - rm -f "$error_file" + rm -f "$error_file" "$sql_file" return "$status" fi } diff --git a/engines/starrocks_engine.sh b/engines/starrocks_engine.sh index d63f618..cec8373 100644 --- a/engines/starrocks_engine.sh +++ b/engines/starrocks_engine.sh @@ -148,6 +148,9 @@ engine_run_sql() { local db="$1" local sql_statement="$2" local capture_last_query_id="${3:-true}" + local error_file="" + local sql_file="" + local status=0 if [ -z "$sql_statement" ]; then echo "ERROR: SQL statement cannot be empty" >&2 @@ -173,15 +176,30 @@ engine_run_sql() { local last_query_id_file="${RESULT_DIR:-/tmp}/.last_query_id" # Execute the SQL statement - if output=$(mysql "${args[@]}" --batch --skip-column-names -e "$mysql_sql" 2>&1); then + error_file="$(mktemp "${TMPDIR:-/tmp}/starrocks_mysql_stderr.XXXXXX")" || { + echo "ERROR: Failed to create temporary stderr file" >&2 + return 1 + } + sql_file="$(mktemp "${TMPDIR:-/tmp}/starrocks_mysql_sql.XXXXXX")" || { + echo "ERROR: Failed to create temporary SQL file" >&2 + rm -f "$error_file" + return 1 + } + printf '%s\n' "$mysql_sql" > "$sql_file" + if output=$(mysql "${args[@]}" --batch --skip-column-names < "$sql_file" 2>"$error_file"); then + rm -f "$sql_file" "$error_file" if [[ "${profile:-}" == "true" && "$capture_last_query_id" == "true" ]]; then echo "$output" | sed '/^[[:space:]]*$/d' | tail -n 1 > "$last_query_id_file" fi return 0 else + status=$? echo "ERROR: Failed to execute SQL statement: $sql_statement" >&2 - echo "$output" >&2 - return 1 + if [ -s "$error_file" ]; then + cat "$error_file" >&2 + fi + rm -f "$error_file" "$sql_file" + return "$status" fi } From 77bfc9db6a0580134dd6148174ceb797aeed751e Mon Sep 17 00:00:00 2001 From: zgxme Date: Tue, 30 Jun 2026 17:29:04 +0800 Subject: [PATCH 3/4] fix: always append last query id SQL --- benchmark.sh | 2 +- engines/doris_engine.sh | 28 ++++++++++++++-------------- engines/interface.sh | 1 - engines/starrocks_engine.sh | 31 ++++++++++++++++++------------- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/benchmark.sh b/benchmark.sh index 9bf22f6..978f4ab 100755 --- a/benchmark.sh +++ b/benchmark.sh @@ -325,7 +325,7 @@ run_session() { echo "Running set session." local session_content session_content=$(envsubst < "$session_file") - if ! engine_run_sql "" "$session_content" false; then + if ! engine_run_sql "" "$session_content"; then die "Setup session failed" fi } diff --git a/engines/doris_engine.sh b/engines/doris_engine.sh index 15b96f9..c977e17 100644 --- a/engines/doris_engine.sh +++ b/engines/doris_engine.sh @@ -271,7 +271,6 @@ engine_run_sql_file() { engine_run_sql() { local db="$1" local sql_statement="$2" - local capture_last_query_id="${3:-true}" local error_file="" local sql_file="" local status=0 @@ -289,14 +288,6 @@ engine_run_sql() { db="$(doris_qualified_db "$db")" [ -n "$db" ] && args+=(-D"$db") - local mysql_sql="$sql_statement" - if [ "$capture_last_query_id" = "true" ]; then - local normalized_sql - normalized_sql=$(printf '%s' "$sql_statement" | sed -e ':trim' -e 's/[[:space:]]*$//' \ - -e '/;$/ { s/;*$//; b trim; }') - mysql_sql="${normalized_sql}; select last_query_id();" - fi - local last_query_id_file="${RESULT_DIR:-/tmp}/.last_query_id" error_file="$(mktemp "${TMPDIR:-/tmp}/doris_mysql_stderr.XXXXXX")" || { echo "ERROR: Failed to create temporary stderr file" >&2 @@ -307,14 +298,23 @@ engine_run_sql() { rm -f "$error_file" return 1 } - printf '%s\n' "$mysql_sql" > "$sql_file" + printf '%s\n' "$sql_statement" > "$sql_file" + local sql_tail="$sql_statement" + while :; do + case "$sql_tail" in + *[[:space:]]) sql_tail="${sql_tail%?}" ;; + *) break ;; + esac + done + case "$sql_tail" in + *";") printf 'select last_query_id();\n' >> "$sql_file" ;; + *) printf ';\nselect last_query_id();\n' >> "$sql_file" ;; + esac if output=$(mysql "${args[@]}" --batch --skip-column-names < "$sql_file" 2>"$error_file"); then rm -f "$sql_file" rm -f "$error_file" - if [ "$capture_last_query_id" = "true" ]; then - # The last non-empty line of stdout is the query ID. - echo "$output" | tail -n 1 > "$last_query_id_file" - fi + # The last non-empty line of stdout is the query ID. + echo "$output" | sed '/^[[:space:]]*$/d' | tail -n 1 > "$last_query_id_file" return 0 else status=$? diff --git a/engines/interface.sh b/engines/interface.sh index 279b2e8..cf87ec6 100644 --- a/engines/interface.sh +++ b/engines/interface.sh @@ -47,7 +47,6 @@ engine_run_sql_file() { # # @param $1: Database name # @param $2: SQL statement to execute -# @param $3: Optional. Whether to apply session SQL first (default: true) # @return: 0 on success, non-zero on failure engine_run_sql() { local db="$1" diff --git a/engines/starrocks_engine.sh b/engines/starrocks_engine.sh index cec8373..f358db1 100644 --- a/engines/starrocks_engine.sh +++ b/engines/starrocks_engine.sh @@ -147,7 +147,6 @@ engine_run_sql_file() { engine_run_sql() { local db="$1" local sql_statement="$2" - local capture_last_query_id="${3:-true}" local error_file="" local sql_file="" local status=0 @@ -165,14 +164,6 @@ engine_run_sql() { db="$(starrocks_qualified_db "$db")" [ -n "$db" ] && args+=(-D"$db") - local mysql_sql="$sql_statement" - if [[ "${profile:-}" == "true" && "$capture_last_query_id" == "true" ]]; then - local normalized_sql - normalized_sql=$(printf '%s' "$sql_statement" | sed -e ':trim' -e 's/[[:space:]]*$//' \ - -e '/;$/ { s/;*$//; b trim; }') - mysql_sql="SET enable_profile = true; ${normalized_sql}; SELECT last_query_id();" - fi - local last_query_id_file="${RESULT_DIR:-/tmp}/.last_query_id" # Execute the SQL statement @@ -185,12 +176,26 @@ engine_run_sql() { rm -f "$error_file" return 1 } - printf '%s\n' "$mysql_sql" > "$sql_file" + if [[ "${profile:-}" == "true" ]]; then + printf 'SET enable_profile = true;\n' > "$sql_file" + else + : > "$sql_file" + fi + printf '%s\n' "$sql_statement" >> "$sql_file" + local sql_tail="$sql_statement" + while :; do + case "$sql_tail" in + *[[:space:]]) sql_tail="${sql_tail%?}" ;; + *) break ;; + esac + done + case "$sql_tail" in + *";") printf 'SELECT last_query_id();\n' >> "$sql_file" ;; + *) printf ';\nSELECT last_query_id();\n' >> "$sql_file" ;; + esac if output=$(mysql "${args[@]}" --batch --skip-column-names < "$sql_file" 2>"$error_file"); then rm -f "$sql_file" "$error_file" - if [[ "${profile:-}" == "true" && "$capture_last_query_id" == "true" ]]; then - echo "$output" | sed '/^[[:space:]]*$/d' | tail -n 1 > "$last_query_id_file" - fi + echo "$output" | sed '/^[[:space:]]*$/d' | tail -n 1 > "$last_query_id_file" return 0 else status=$? From 7aad94aa806bc5bac1a308256cb55e5c81e5699e Mon Sep 17 00:00:00 2001 From: zgxme Date: Wed, 1 Jul 2026 10:55:54 +0800 Subject: [PATCH 4/4] debug --- benchmark.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/benchmark.sh b/benchmark.sh index 978f4ab..5bd25ef 100755 --- a/benchmark.sh +++ b/benchmark.sh @@ -531,6 +531,7 @@ run_timed_query() { local start_time start_time=$(date +%s%3N) + sleep 1 if engine_run_sql "${db}" "$sql_content"; then local end_time end_time=$(date +%s%3N)