1
1
#! /bin/bash
2
2
3
+ # Simple logging
4
+ log () {
5
+ echo " [$( date ' +%H:%M:%S' ) ] $1 "
6
+ }
7
+
8
+ log_error () {
9
+ echo " [$( date ' +%H:%M:%S' ) ] ERROR: $1 " >&2
10
+ }
11
+
12
+ log_step () {
13
+ echo " [$( date ' +%H:%M:%S' ) ] [$1 /$2 ] $3 "
14
+ }
15
+
3
16
# Parse arguments
4
17
while [[ $# -gt 0 ]]; do
5
18
case " $1 " in
@@ -16,24 +29,23 @@ while [[ $# -gt 0 ]]; do
16
29
DATE_ARG=" $1 "
17
30
shift
18
31
else
19
- echo " Unknown parameter: $1 "
32
+ log_error " Unknown parameter: $1 "
20
33
exit 1
21
34
fi
22
35
;;
23
36
esac
24
37
done
25
38
26
- # Check required parameters
39
+ # Validate parameters
27
40
if [[ -z " $STAGE " || -z " $DATE_ARG " ]]; then
28
- echo " Missing required parameters: --stage or yyyymmdd date"
41
+ log_error " Missing required parameters: --stage or yyyymmdd date"
29
42
exit 1
30
43
fi
31
44
32
- # If DSN not provided, try to get from environment variable
33
45
if [[ -z " $DSN " ]]; then
34
46
DSN=" $BENDSQL_DSN "
35
47
if [[ -z " $DSN " ]]; then
36
- echo " --dsn parameter not provided and BENDSQL_DSN environment variable not set"
48
+ log_error " DSN not provided and BENDSQL_DSN not set"
37
49
exit 1
38
50
fi
39
51
fi
@@ -43,93 +55,141 @@ YEAR=${DATE_ARG:0:4}
43
55
MONTH=${DATE_ARG: 4: 2}
44
56
DAY=${DATE_ARG: 6: 2}
45
57
FORMATTED_DATE=" ${YEAR} -${MONTH} -${DAY} "
58
+ TAR_FILE=" data_${FORMATTED_DATE} .tar.gz"
59
+
60
+ log " Starting log restoration for date: ${FORMATTED_DATE} "
61
+ log " Source stage: @${STAGE} , Target file: ${TAR_FILE} "
46
62
47
- # 1. Get download presigned URL
48
- DOWNLOAD_SQL=" PRESIGN DOWNLOAD @${STAGE} /data_${FORMATTED_DATE} .tar.gz"
63
+ # Step 1: Generate download URL
64
+ log_step " 1" " 6" " Generating presigned download URL for @${STAGE} /${TAR_FILE} "
65
+ DOWNLOAD_SQL=" PRESIGN DOWNLOAD @${STAGE} /${TAR_FILE} "
49
66
DOWNLOAD_URL=$( bendsql --dsn " ${DSN} " --query=" ${DOWNLOAD_SQL} " | awk ' {print $3}' )
50
67
51
68
if [[ -z " $DOWNLOAD_URL " ]]; then
52
- echo " Failed to get download URL"
69
+ log_error " Failed to generate download URL for ${TAR_FILE} "
53
70
exit 1
54
71
fi
72
+ log " Download URL generated successfully"
55
73
56
- # 2. Download the file
57
- TAR_FILE=" data_${FORMATTED_DATE} .tar.gz"
58
- echo " Downloading file: ${TAR_FILE} "
59
- curl -o " ${TAR_FILE} " " ${DOWNLOAD_URL} "
74
+ # Step 2: Download backup
75
+ log_step " 2" " 6" " Downloading ${TAR_FILE} from stage @${STAGE} "
76
+ curl -s -o " ${TAR_FILE} " " ${DOWNLOAD_URL} "
60
77
61
78
if [[ ! -f " ${TAR_FILE} " ]]; then
62
- echo " File download failed "
79
+ log_error " Failed to download ${TAR_FILE} "
63
80
exit 1
64
81
fi
65
82
66
- # 3. Extract the file
67
- echo " Extracting file: ${TAR_FILE} "
83
+ FILE_SIZE=$( du -h " ${TAR_FILE} " | cut -f1)
84
+ log " Downloaded ${TAR_FILE} successfully (${FILE_SIZE} )"
85
+
86
+ # Step 3: Extract archive
87
+ log_step " 3" " 6" " Extracting ${TAR_FILE} to temporary directory"
68
88
TEMP_DIR=" temp_extracted_${DATE_ARG} "
69
89
mkdir -p " ${TEMP_DIR} "
70
90
tar -xzf " ${TAR_FILE} " -C " ${TEMP_DIR} "
71
91
72
- # 4. Process and upload each file
92
+ EXTRACTED_FILES=$( find " ${TEMP_DIR} " -type f | wc -l)
93
+ log " Extracted ${EXTRACTED_FILES} files from ${TAR_FILE} "
94
+
95
+ # Step 4: Detect path prefix
96
+ log_step " 4" " 6" " Analyzing directory structure for path prefix"
97
+ TARGET_DIRS=(" columns" " user_functions" " query_raw_logs" " query_logs" " query_profile_logs" )
98
+ PREFIX=" "
99
+
100
+ for target_dir in " ${TARGET_DIRS[@]} " ; do
101
+ SAMPLE_FILE=$( find " ${TEMP_DIR} " -path " */${target_dir} /*" -type f | head -1)
102
+ if [[ -n " $SAMPLE_FILE " ]]; then
103
+ RELATIVE_PATH=" ${SAMPLE_FILE# ${TEMP_DIR} / } "
104
+ PREFIX=$( echo " $RELATIVE_PATH " | sed " s|/${target_dir} /.*||" | sed " s|${target_dir} /.*||" )
105
+ if [[ -n " $PREFIX " ]]; then
106
+ PREFIX=" ${PREFIX} /"
107
+ fi
108
+ break
109
+ fi
110
+ done
111
+
112
+ if [[ -n " $PREFIX " ]]; then
113
+ log " Path prefix detected: '${PREFIX} ' - will be stripped during upload"
114
+ else
115
+ log " No path prefix detected - using original file paths"
116
+ fi
117
+
118
+ # Step 5: Upload files
73
119
UPLOAD_STAGE=" ${STAGE} _${YEAR} _${MONTH} _${DAY} "
120
+ log_step " 5" " 6" " Uploading ${EXTRACTED_FILES} files to stage @${UPLOAD_STAGE} "
121
+
122
+ bendsql --dsn " ${DSN} " --query=" DROP STAGE IF EXISTS ${UPLOAD_STAGE} " > /dev/null 2>&1
123
+ bendsql --dsn " ${DSN} " --query=" CREATE STAGE ${UPLOAD_STAGE} " > /dev/null 2>&1
124
+ log " Created destination stage: @${UPLOAD_STAGE} "
74
125
75
- bendsql --dsn " ${DSN} " --query=" DROP STAGE IF EXISTS ${UPLOAD_STAGE} "
76
- bendsql --dsn " ${DSN} " --query=" CREATE STAGE ${UPLOAD_STAGE} "
126
+ TOTAL_FILES=$( find " ${TEMP_DIR} " -type f | wc -l)
127
+ CURRENT_FILE=0
128
+ UPLOAD_SUCCESS=0
129
+ UPLOAD_FAILED=0
77
130
78
131
find " ${TEMP_DIR} " -type f | while read -r FILE; do
132
+ CURRENT_FILE=$(( CURRENT_FILE + 1 ))
79
133
RELATIVE_PATH=" ${FILE# ${TEMP_DIR} / } "
80
-
81
- # Get upload presigned URL
82
- UPLOAD_SQL=" PRESIGN UPLOAD @${UPLOAD_STAGE} /${RELATIVE_PATH} "
83
- UPLOAD_URL=$( bendsql --dsn " ${DSN} " --query=" ${UPLOAD_SQL} " | awk ' {print $3}' )
84
-
85
- if [[ -z " $UPLOAD_URL " ]]; then
86
- echo " Failed to get upload URL for: ${RELATIVE_PATH} "
87
- continue
134
+
135
+ if [[ -n " $PREFIX " && " $RELATIVE_PATH " == ${PREFIX} * ]]; then
136
+ UPLOAD_PATH=" ${RELATIVE_PATH# ${PREFIX} } "
137
+ else
138
+ UPLOAD_PATH=" $RELATIVE_PATH "
88
139
fi
89
140
90
- echo " Uploading file: ${RELATIVE_PATH} "
91
- curl -X PUT -T " ${FILE} " " ${UPLOAD_URL} "
141
+ printf " \rUploading: %d/%d files (Success: %d, Failed: %d)" " $CURRENT_FILE " " $TOTAL_FILES " " $UPLOAD_SUCCESS " " $UPLOAD_FAILED "
92
142
93
- if [[ $? -eq 0 ]]; then
94
- echo " Upload successful: ${RELATIVE_PATH} "
143
+ UPLOAD_SQL=" PRESIGN UPLOAD @${UPLOAD_STAGE} /${UPLOAD_PATH} "
144
+ UPLOAD_URL=$( bendsql --dsn " ${DSN} " --query=" ${UPLOAD_SQL} " | awk ' {print $3}' )
145
+
146
+ if [[ -n " $UPLOAD_URL " ]]; then
147
+ if curl -s -X PUT -T " ${FILE} " " ${UPLOAD_URL} " ; then
148
+ UPLOAD_SUCCESS=$(( UPLOAD_SUCCESS + 1 ))
149
+ else
150
+ UPLOAD_FAILED=$(( UPLOAD_FAILED + 1 ))
151
+ fi
95
152
else
96
- echo " Upload failed: ${RELATIVE_PATH} "
153
+ UPLOAD_FAILED= $(( UPLOAD_FAILED + 1 ))
97
154
fi
98
155
done
99
156
100
- # Cleanup temporary files
101
- echo " Cleaning up temporary files"
102
- rm -rf " ${TEMP_DIR} "
103
- rm -f " ${TAR_FILE} "
104
- echo " Temporary files cleanup is finished."
157
+ echo # New line after progress
158
+ log " Upload completed: ${UPLOAD_SUCCESS} successful, ${UPLOAD_FAILED} failed"
159
+
160
+ # Cleanup
161
+ log " Cleaning up: removing ${TEMP_DIR} and ${TAR_FILE} "
162
+ rm -rf " ${TEMP_DIR} " " ${TAR_FILE} "
105
163
164
+ # Step 6: Restore database
106
165
RESTORE_DATABASE=" ${STAGE} _${YEAR} _${MONTH} _${DAY} "
107
- bendsql --dsn " ${DSN} " --query=" DROP DATABASE IF EXISTS ${RESTORE_DATABASE} "
108
- bendsql --dsn " ${DSN} " --query=" CREATE DATABASE ${RESTORE_DATABASE} "
109
-
110
- echo " Restoring the '${RESTORE_DATABASE} .columns' table..."
111
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" create table columns like system.columns;"
112
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" COPY INTO columns FROM @${UPLOAD_STAGE} /columns;"
113
- echo " The '${RESTORE_DATABASE} .columns' table has been successfully restored"
114
-
115
- echo " Restoring the '${RESTORE_DATABASE} .user_functions' table..."
116
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" create table user_functions like system.user_functions;"
117
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" COPY INTO user_functions FROM @${UPLOAD_STAGE} /user_functions;"
118
- echo " The '${RESTORE_DATABASE} .user_functions' table has been successfully restored"
119
-
120
- echo " Restoring the '${RESTORE_DATABASE} .log_history' table..."
121
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" create table log_history like system_history.log_history;"
122
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" COPY INTO log_history FROM @${UPLOAD_STAGE} /query_raw_logs;"
123
- echo " The '${RESTORE_DATABASE} .log_history' table has been successfully restored"
124
-
125
- echo " Restoring the '${RESTORE_DATABASE} .query_history' table..."
126
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" create table query_history like system_history.query_history;"
127
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" COPY INTO query_history FROM @${UPLOAD_STAGE} /query_logs;"
128
- echo " The '${RESTORE_DATABASE} .query_history' table has been successfully restored"
129
-
130
- echo " Restoring the '${RESTORE_DATABASE} .profile_history' table..."
131
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" create table profile_history like system_history.profile_history;"
132
- bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" COPY INTO profile_history FROM @${UPLOAD_STAGE} /query_profile_logs;"
133
- echo " The '${RESTORE_DATABASE} .profile_history' table has been successfully restored"
134
-
135
- echo " Processing completed"
166
+ log_step " 6" " 6" " Creating database '${RESTORE_DATABASE} ' and restoring tables"
167
+
168
+ bendsql --dsn " ${DSN} " --query=" DROP DATABASE IF EXISTS ${RESTORE_DATABASE} " > /dev/null 2>&1
169
+ bendsql --dsn " ${DSN} " --query=" CREATE DATABASE ${RESTORE_DATABASE} " > /dev/null 2>&1
170
+ log " Created database: ${RESTORE_DATABASE} "
171
+
172
+ # Restore tables
173
+ declare -A TABLE_MAP=(
174
+ [" columns" ]=" system.columns:columns"
175
+ [" user_functions" ]=" system.user_functions:user_functions"
176
+ [" log_history" ]=" system_history.log_history:query_raw_logs"
177
+ [" query_history" ]=" system_history.query_history:query_logs"
178
+ [" profile_history" ]=" system_history.profile_history:query_profile_logs"
179
+ )
180
+
181
+ for table_name in " ${! TABLE_MAP[@]} " ; do
182
+ IFS=' :' read -r source_table source_path <<< " ${TABLE_MAP[$table_name]}"
183
+
184
+ log " Restoring table: ${RESTORE_DATABASE} .${table_name} from @${UPLOAD_STAGE} /${source_path} "
185
+
186
+ bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" CREATE TABLE ${table_name} LIKE ${source_table} ;" > /dev/null 2>&1
187
+ bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" COPY INTO ${table_name} FROM @${UPLOAD_STAGE} /${source_path} ;" > /dev/null 2>&1
188
+
189
+ ROW_COUNT=$( bendsql --dsn " ${DSN} " --database " ${RESTORE_DATABASE} " --query=" SELECT COUNT(*) FROM ${table_name} ;" | tail -1)
190
+ log " Table ${table_name} restored: ${ROW_COUNT} rows"
191
+ done
192
+
193
+ log " Log restoration completed successfully"
194
+ log " Restored database: ${RESTORE_DATABASE} "
195
+ log " Tables available: columns, user_functions, log_history, query_history, profile_history"
0 commit comments