3a4ccfa07aaa2c5ad3d8b4dfbf517a898b6c9781
[policy/docker.git] / policy-db-migrator / src / main / docker / db-migrator
1 #!/usr/bin/env sh
2
3 # ============LICENSE_START=======================================================
4 # ONAP
5 # ================================================================================
6 # Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved.
7 # Modifications Copyright (C) 2021-2022 Nordix Foundation.
8 # ================================================================================
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
12 #
13 #      http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
20 # ============LICENSE_END=========================================================
21
22 # #####################################################################
23 #
24 # Upgrade/Downgrade SQL File Name Format:
25 #
26 #     <VERSION>-<pdp|feature-name>[-description](.upgrade|.downgrade).sql
27 #
28 # This tool operates on a migration working directory at
29 #
30 #    $POLICY_HOME/etc/db/migration
31 #
32 # Upgrade/Downgrade files for each schema (aka database) names to be maintained
33 # by this tool are located at
34 #
35 #    $POLICY_HOME/etc/db/migration/<schema-name>/sql
36 #
37 # The nature of the migration directories is dynamic.
38 # A number of environment variables needs to be initialized
39 # prior to running db-migrator.
40 # These vaiables specifiy the connection details for the database
41 # to be upgraded/downgraded.
42 #
43 # The repository of upgrade/downgrade scripts is located in the
44 # /home/policy/sql directory.
45 # Two additional scripts have been provided to prepare the directories/files
46 # needed to perform the upgrade/downgrade.
47 #
48 # At any given time the following invariant must be preserved in any given
49 # $POLICY_HOME/etc/db/migration/<schema-name>/sql directory
50 #
51 #     There is only upgrade scripts, or only downgrade scripts, or none.
52 #
53 # #####################################################################
54
55 source ${POLICY_HOME}/etc/profile.d/env.sh
56
57 METADATA_DB=migration
58 METADATA_TABLE=${METADATA_DB}.schema_versions
59 MIGRATION_DIR=${POLICY_HOME}/etc/db/migration
60 ZERO_VERSION="0"
61 BASE_VERSION="0800"
62 UPGRADE_SQL_SUFFIX=".upgrade.sql"
63 DOWNGRADE_SQL_SUFFIX=".downgrade.sql"
64
65 SQL_QUOTES="SET SESSION SQL_MODE=ANSI_QUOTES;"
66
67 #####################################################
68 # usage
69 #####################################################
70
71 function usage() {
72     echo
73     echo -e "syntax: $(basename "$0") "
74     echo -e "\t -s <schema-name> "
75     echo -e "\t [-b <migration-dir>] "
76     echo -e "\t [-f <from-version>]"
77     echo -e "\t [-t <target-version>]"
78     echo -e "\t -o <operations> "
79     echo
80     echo -e "\t where <operations>=upgrade|downgrade|auto|version|erase|report"
81     echo
82     echo
83     echo -e "Configuration Options:"
84     echo -e "\t -s|--schema|--database:  schema to operate on ('ALL' to apply on all)"
85     echo -e "\t -b|--basedir: overrides base DB migration directory"
86     echo -e "\t -f|--from: overrides current release version for operations"
87     echo -e "\t -t|--target: overrides target release to upgrade/downgrade"
88     echo
89     echo -e "Operations:"
90     echo -e "\t upgrade: upgrade operation"
91     echo -e "\t downgrade: performs a downgrade operation"
92     echo -e "\t auto: autonomous operation, determines upgrade or downgrade"
93     echo -e "\t version: returns current version, and in conjunction if '-f' sets the current version"
94     echo -e "\t erase: erase all data related <schema> (use with care)"
95     echo -e "\t report: migration detailed report on an schema"
96     echo -e "\t ok: is the migration status valid"
97     echo
98     echo
99 }
100
101 #####################################################
102 # current_schema
103 #####################################################
104
105 function current_schema() {
106     if [ "${DEBUG}" = "y" ]; then
107         echo "-- current_schema --"
108         set -x
109     fi
110
111     local rc
112     local query="SELECT count(table_name) from information_schema.tables where table_schema='${SCHEMA}'"
113
114     TABLES_IN_SCHEMA=$(${MYSQL} --skip-column-names --silent --execute "${query}")
115     if [ ${TABLES_IN_SCHEMA} -gt 0 ] && [ "${BASE_VERSION}" \> "${CURRENT_RELEASE}" ]; then
116         set_current_release "${BASE_VERSION}"
117         return $?
118     fi
119
120     return 0
121 }
122
123 #####################################################
124 # ensure global metadata
125 #####################################################
126
127 function ensure_metadata() {
128     if [ "${DEBUG}" = "y" ]; then
129         echo "-- ensure_metadata --"
130         set -x
131     fi
132
133     local sql rc
134
135     sql="CREATE DATABASE IF NOT EXISTS ${METADATA_DB};"
136     ${MYSQL} --execute "${sql}"
137     rc=$?
138     if [ ${rc} -ne 0 ]; then
139         return ${rc}
140     fi
141
142     sql="CREATE TABLE IF NOT EXISTS ${METADATA_TABLE} "
143     sql=${sql}"(name VARCHAR(60) NOT NULL, version VARCHAR(20), "
144     sql=${sql}"PRIMARY KEY(name));"
145     ${MYSQL} --execute "${sql}"
146     return $?
147 }
148
149 #####################################################
150 # ensure metadata on a per schema basis
151 #####################################################
152
153 function ensure_metadata_schema() {
154     if [ "${DEBUG}" = "y" ]; then
155         echo "-- ensure_metadata_schema --"
156         set -x
157     fi
158
159     local sql rc
160
161     sql="CREATE TABLE IF NOT EXISTS ${METADATA_HISTORY} "
162     sql=${sql}"(ID bigint(20) unsigned NOT NULL AUTO_INCREMENT, script VARCHAR(80) NOT NULL, "
163     sql=${sql}"operation VARCHAR(10), from_version VARCHAR(20), to_version VARCHAR(20), tag VARCHAR(20), "
164     sql=${sql}"success VARCHAR(1), atTime TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, "
165     sql=${sql}"PRIMARY KEY(ID));"
166     ${MYSQL} --execute "${sql}"
167     rc=$?
168     if [ ${rc} -ne 0 ]; then
169         return ${rc}
170     fi
171
172     sql="CREATE DATABASE IF NOT EXISTS ${SCHEMA_DB};"
173     ${MYSQL} --execute "${sql}"
174     return $?
175 }
176
177 #####################################################
178 # target_release
179 #####################################################
180
181 function target_release() {
182     if [ "${DEBUG}" = "y" ]; then
183         echo "-- target_release --"
184         set -x
185     fi
186
187     local sql sqlName upgradeSqls downgradeSqls
188
189     TARGET_UPGRADE_RELEASE=${ZERO_VERSION}
190     TARGET_DOWNGRADE_RELEASE=${ZERO_VERSION}
191
192     upgradeSqls=$(ls -v -r "${UPGRADE_DIR}"/*/upgrade/*.sql 2>/dev/null)
193     for sql in ${upgradeSqls}; do
194         TARGET_UPGRADE_RELEASE="$(basename $(dirname $(dirname $sql)))"
195         break
196     done
197
198     # default unless overriden
199     TARGET_DOWNGRADE_RELEASE="${ZERO_VERSION}"
200 }
201
202 #####################################################
203 # is_upgrade
204 #####################################################
205
206 function is_upgrade() {
207     if [ "${DEBUG}" = "y" ]; then
208         echo "-- is_upgrade --"
209         set -x
210     fi
211
212     local upgradeSqls
213
214     upgradeSqls=$(ls -v "${UPGRADE_DIR}"/*/upgrade/*.sql 2>/dev/null)
215     if [ -z "${upgradeSqls}" ]; then
216         return 1
217     else
218         return 0
219     fi
220 }
221
222 #####################################################
223 # is_downgrade
224 #####################################################
225
226 function is_downgrade() {
227     if [ "${DEBUG}" = "y" ]; then
228         echo "-- is_downgrade --"
229         set -x
230     fi
231
232     local downgradeSqls
233
234     downgradeSqls=$(ls -v -r "${DOWNGRADE_DIR}"/*/downgrade/*.sql 2>/dev/null)
235     if [ -z "${downgradeSqls}" ]; then
236         return 1
237     else
238         return 0
239     fi
240 }
241
242 #####################################################
243 # set_current_release
244 #####################################################
245
246 function set_current_release() {
247     if [ "${DEBUG}" = "y" ]; then
248         echo "-- set_current_release --"
249         set -x
250     fi
251
252     CURRENT_RELEASE="${1}"
253
254     local sql
255     sql="INSERT INTO ${METADATA_TABLE} (name, version) "
256     sql=${sql}"VALUES('${SCHEMA}', '${CURRENT_RELEASE}') "
257     sql=${sql}"ON DUPLICATE KEY UPDATE version='${CURRENT_RELEASE}';"
258
259     ${MYSQL} --execute "${sql}"
260     return $?
261 }
262
263 #####################################################
264 # current_release
265 #####################################################
266
267 function current_release() {
268     if [ "${DEBUG}" = "y" ]; then
269         echo "-- current_release --"
270         set -x
271     fi
272
273     local rc
274     local query="SELECT version FROM ${METADATA_TABLE} WHERE name='${SCHEMA}'"
275
276     CURRENT_RELEASE=$(${MYSQL} --skip-column-names --silent --execute "${query}")
277     if [ -z "${CURRENT_RELEASE}" ]; then
278         set_current_release "${ZERO_VERSION}"
279         return $?
280     fi
281
282     return 0
283 }
284
285 #####################################################
286 # previous_release
287 #####################################################
288
289 function previous_release() {
290     if [ "${DEBUG}" = "y" ]; then
291         echo "-- previous_release --"
292         set -x
293     fi
294     local current_release="${1}"
295     local current_release_int_val previous_release_int_val previous_release
296
297     if [ $current_release == $ZERO_VERSION ] || [ $current_release == $BASE_VERSION ]; then
298         PREVIOUS_RELEASE=$ZERO_VERSION
299     else
300         current_release_int_val=$(echo $current_release | awk '{$0=int($0)}1')
301         let previous_release_int_val=$current_release_int_val-100
302         if [ $previous_release_int_val -lt 1000 ]; then
303             previous_release="0"$previous_release_int_val
304         else
305             previous_release=$previous_release_int_val
306         fi
307         PREVIOUS_RELEASE=$previous_release
308     fi
309
310     return 0
311 }
312
313 #####################################################
314 # last_operation_status
315 #####################################################
316
317 function last_operation_status() {
318     if [ "${DEBUG}" = "y" ]; then
319         echo "-- last_operation_status --"
320         set -x
321     fi
322
323     local query rc row
324
325     query="SELECT script, operation, from_version, to_version, success FROM  "
326     query=${query}"${METADATA_HISTORY} WHERE id="
327     query=${query}"(SELECT MAX(id) from ${METADATA_HISTORY}) "
328     query=${query}"AND success=0"
329
330     row=$(${MYSQL} --skip-column-names --silent --execute "${query}")
331
332     if [ "${row}" != "" ]; then
333         LAST_SCRIPT=$(echo $row | awk '{print $1}')
334         LAST_OPERATION=$(echo $row | awk '{print $2}')
335         LAST_FROM_VERSION=$(echo $row | awk '{print $3}')
336         LAST_TO_VERSION=$(echo $row | awk '{print $4}')
337         LAST_STATUS=$(echo $row | awk '{print $5}')
338         rc=0
339     else
340         rc=1
341     fi
342
343     return $rc
344 }
345
346 #####################################################
347 # execute sql script history
348 #####################################################
349
350 function track_script() {
351     if [ "${DEBUG}" = "y" ]; then
352         echo "-- track_script $* --"
353         set -x
354     fi
355
356     local script="${1}" operation="${2}" success="${3}" from_version="${4}" to_version="${5}" tag="${6}"
357     if [ $operation == "downgrade" ]; then
358         to_version=${TARGET_DOWNGRADE_RELEASE}
359     fi
360
361     local sql="INSERT INTO ${METADATA_HISTORY}(script,operation,from_version,to_version,tag,success,atTime) "
362     sql=${sql}"VALUES ('${script}','${operation}','${from_version}','${to_version}','${tag}','${success}',now()) "
363
364     ${MYSQL} --execute "${sql}"
365     return $?
366 }
367
368 #####################################################
369 # execute sql script
370 #####################################################
371
372 function run_script() {
373     if [ "${DEBUG}" == "y" ]; then
374         echo "-- run_script $* --"
375         set -x
376     fi
377
378     local operation="${1}" script="${2}" scriptPath="${3}" fromVersion="${4}" toVersion="${5}" tag="${6}"
379
380     echo
381     echo "> ${operation} ${script}"
382
383     ${MYSQL} ${SCHEMA} --verbose <"${scriptPath}"
384     local rc=$?
385     if [ ${rc} -ne 0 ]; then
386         success="0"
387     else
388         success="1"
389     fi
390
391     track_script "${script}" "${operation}" "${success}" "${fromVersion}" "${toVersion}" "${tag}"
392
393     return ${rc}
394 }
395
396 #####################################################
397 # upgrade
398 #####################################################
399
400 function upgrade() {
401     if [ "${DEBUG}" = "y" ]; then
402         echo "-- upgrade --"
403         set -x
404     fi
405
406     local sqlName sqlFile schemaVersion upgradeSqls rc tagDate tag
407     tagDate=$(date +%d%m%y%H%M%S)
408
409     echo "upgrade: ${CURRENT_RELEASE} -> ${TARGET_UPGRADE_RELEASE}"
410
411     if [ ${CURRENT_RELEASE} \< ${TARGET_UPGRADE_RELEASE} ]; then
412         upgradeSqls=$(ls -v "${UPGRADE_DIR}"/*/upgrade/*.sql 2>/dev/null)
413         for sqlFile in ${upgradeSqls}; do
414             sqlName=$(basename "${sqlFile}")
415             schemaVersion="$(basename $(dirname $(dirname $sqlFile)))"
416             previous_release $schemaVersion
417             if [ "${schemaVersion}" -gt "${CURRENT_RELEASE}" ] &&
418                 [ "${schemaVersion}" -le "${TARGET_UPGRADE_RELEASE}" ]; then
419                 tag=${tagDate}"${schemaVersion}u"
420                 if [ $RETRY -eq 1 ] &&
421                     # Compare the numeric portion of the filename because shell doesn't support string comparison
422                     [ $(echo ${sqlName} | awk -F- '{print $1}') -${COMPARE} $(echo ${LAST_SCRIPT} | awk -F- '{print $1}') ]; then
423                     rc=1
424                 else
425                     rc=0
426                 fi
427                 if [ ${rc} -eq 0 ]; then
428                     run_script "upgrade" "${sqlName}" "${sqlFile}" "${PREVIOUS_RELEASE}" "${schemaVersion}" "${tag}"
429                     rc=$?
430                     if [ ${rc} -ne 0 ]; then
431                         echo "${SCHEMA}: upgrade aborted at ${schemaVersion} by script ${sqlName}"
432                         set_current_release "${schemaVersion}"
433                         return ${rc}
434                     fi
435                 fi
436             fi
437         done
438
439         set_current_release "${TARGET_UPGRADE_RELEASE}"
440     fi
441
442     return 0
443 }
444
445 #####################################################
446 # downgrade
447 #####################################################
448
449 function downgrade() {
450     if [ "${DEBUG}" = "y" ]; then
451         echo "-- downgrade --"
452         set -x
453     fi
454
455     local sqlName sqlFile schemaVersion downgradeSqls rc tagDate tag
456     tagDate=$(date +%d%m%y%H%M%S)
457
458     echo "downgrade: ${CURRENT_RELEASE} -> ${TARGET_DOWNGRADE_RELEASE}"
459
460     if [ ${CURRENT_RELEASE} \> ${TARGET_DOWNGRADE_RELEASE} ]; then
461         downgradeSqls=$(ls -v -r "${DOWNGRADE_DIR}"/*/downgrade/*.sql 2>/dev/null)
462         for sqlFile in ${downgradeSqls}; do
463             sqlName=$(basename "${sqlFile}")
464             schemaVersion="$(basename $(dirname $(dirname $sqlFile)))"
465             if [ "${schemaVersion}" -le "${CURRENT_RELEASE}" ] &&
466                 [ "${schemaVersion}" -gt "${TARGET_DOWNGRADE_RELEASE}" ]; then
467                 tag=${tagDate}"${schemaVersion}d"
468                 if [ $RETRY -eq 1 ] &&
469                     # Compare the numeric portion of the filename because shell doesn't support string comparison
470                     [ $(echo ${sqlName} | awk -F- '{print $1}') -${COMPARE} $(echo ${LAST_SCRIPT} | awk -F- '{print $1}') ]; then
471                     rc=1
472                 else
473                     rc=0
474                 fi
475                 if [ ${rc} -eq 0 ]; then
476                     run_script "downgrade" "${sqlName}" "${sqlFile}" "${schemaVersion}" "${PREVIOUS_RELEASE}" ${tag}
477                     rc=$?
478                     if [ ${rc} -ne 0 ]; then
479                         echo "${SCHEMA}: downgrade aborted at ${schemaVersion} by script ${sqlName}"
480                         set_current_release "${schemaVersion}"
481                         return ${rc}
482                     fi
483                 fi
484             fi
485         done
486
487         set_current_release "${TARGET_DOWNGRADE_RELEASE}"
488     fi
489
490     return 0
491 }
492
493 #####################################################
494 # erase
495 #####################################################
496
497 function erase() {
498     if [ "${DEBUG}" = "y" ]; then
499         echo "-- erase --"
500         set -x
501     fi
502
503     local updateMetadata="UPDATE ${METADATA_TABLE} SET version='${ZERO_VERSION}';"
504     ${MYSQL} --execute "${updateMetadata}"
505
506     local deleteHistory="DELETE FROM ${METADATA_HISTORY};"
507     ${MYSQL} --execute "${deleteHistory}"
508
509     local dropDB="DROP DATABASE IF EXISTS ${SCHEMA_DB}"
510     ${MYSQL} --execute "${dropDB}"
511 }
512
513 #####################################################
514 # report
515 #####################################################
516
517 function report() {
518     if [ "${DEBUG}" = "y" ]; then
519         echo "-- report --"
520         set -x
521     fi
522
523     local versionSql="SELECT * FROM ${METADATA_TABLE} WHERE name='${SCHEMA}';"
524     ${MYSQL} --execute "${versionSql}"
525
526     local historySql="SELECT * FROM ${METADATA_HISTORY} ORDER BY id, atTime ASC;"
527     ${MYSQL} --execute "${historySql}"
528
529     okay
530 }
531
532 function okay() {
533     if [ "${DEBUG}" = "y" ]; then
534         echo "-- okay --"
535         set -x
536     fi
537
538     local rc=0
539     if is_upgrade; then
540         if [ "${CURRENT_RELEASE}" = "${TARGET_UPGRADE_RELEASE}" ]; then
541             echo "${SCHEMA}: OK @ ${CURRENT_RELEASE}"
542         else
543             echo "${SCHEMA}: upgrade available: ${CURRENT_RELEASE} -> ${TARGET_UPGRADE_RELEASE}"
544             rc=1
545         fi
546     else
547         if [ "${CURRENT_RELEASE}" = "${TARGET_DOWNGRADE_RELEASE}" ]; then
548             echo "${SCHEMA}: OK @ ${CURRENT_RELEASE}"
549         else
550             echo "${SCHEMA}: downgrade available: ${CURRENT_RELEASE} -> ${TARGET_DOWNGRADE_RELEASE}"
551             rc=1
552         fi
553     fi
554
555     return ${rc}
556 }
557
558 #####################################################
559 # MAIN
560 #####################################################
561
562 if [ "${DEBUG}" = "y" ]; then
563     echo "-- $0 $* --"
564     set -x
565 fi
566 until [ -z "$1" ]; do
567     case $1 in
568     -s | --schema | --database)
569         shift
570         SCHEMA=$1
571         ;;
572     -b | --basedir)
573         shift
574         MIGRATION_DIR=$1
575         ;;
576     -t | --target)
577         shift
578         INPUT_TARGET_RELEASE=$1
579         ;;
580     -f | --from)
581         shift
582         INPUT_FROM_RELEASE=$1
583         ;;
584     -o | --operation)
585         shift
586         OPERATION=$1
587         ;;
588     *)
589         usage
590         exit 1
591         ;;
592     esac
593     shift
594 done
595
596 case ${OPERATION} in
597 upgrade) ;;
598 downgrade) ;;
599 auto) ;;
600 version) ;;
601 erase) ;;
602 report) ;;
603 ok) ;;
604 *)
605     echo "error: invalid operation provided"
606     usage
607     exit 1
608     ;;
609 esac
610
611 if [ -z "${SCHEMA}" ]; then
612     echo "error: a database name must be provided"
613     usage
614     exit 2
615 fi
616
617 source "${POLICY_HOME}"/etc/profile.d/env.sh
618
619 if [ -z "${SQL_HOST}" ] || [ -z "${SQL_USER}" ] || [ -z "${SQL_PASSWORD}" ]; then
620     echo "error: no database has been set up"
621     exit 4
622 fi
623
624 if [ -z "$MYSQL_CMD" ]; then
625     MYSQL_CMD="mysql"
626 fi
627
628 MYSQL="${MYSQL_CMD} -u${SQL_USER} -p${SQL_PASSWORD} -h ${SQL_HOST}"
629 if ! ${MYSQL} -h"${SQL_HOST}" --execute "show databases;" >/dev/null 2>&1; then
630     echo "error: No DB connectivity to ${SQL_HOST} for ${SQL_USER}"
631     exit 5
632 fi
633
634 if [ "${SCHEMA}" = "ALL" ]; then
635     SCHEMA="*"
636 fi
637
638 SCHEMA_S=$(ls -d "${MIGRATION_DIR}"/${SCHEMA}/ 2>/dev/null)
639 if [ -z "${SCHEMA_S}" ]; then
640     echo "error: no databases available"
641     exit 0
642 fi
643
644 if ! ensure_metadata; then
645     echo "error: migration metadata not accessible"
646     exit 7
647 fi
648
649 rc=0
650 for dbPath in ${SCHEMA_S}; do
651     SCHEMA=$(basename "${dbPath}")
652     SCHEMA_DB="\`${SCHEMA}\`"
653     UPGRADE_DIR="${MIGRATION_DIR}"/"${SCHEMA}"/sql
654     DOWNGRADE_DIR=${UPGRADE_DIR}
655     METADATA_HISTORY="${METADATA_DB}.\`${SCHEMA}_schema_changelog\`"
656     TARGET_RELEASE=${INPUT_TARGET_RELEASE}
657
658     if is_upgrade && is_downgrade; then
659         echo "${SCHEMA}: failure: invalid configuration: ${UPGRADE_SQL_SUFFIX} and " \
660             "${DOWNGRADE_SQL_SUFFIX} exist under ${DOWNGRADE_DIR}"
661         rc=1
662         continue
663     fi
664
665     if [ "${operation}" = "auto" ]; then
666         if is_upgrade; then
667             operation=upgrade
668         else
669             operation=downgrade
670         fi
671     fi
672
673     if ! ensure_metadata_schema; then
674         echo "${SCHEMA}: failure: metadata not accessible for this schema"
675         continue
676     fi
677
678     if [ -z "${TARGET_RELEASE}" ]; then
679         target_release
680     else
681         # user asked to override
682         TARGET_UPGRADE_RELEASE="${TARGET_RELEASE}"
683         TARGET_DOWNGRADE_RELEASE="${TARGET_RELEASE}"
684     fi
685
686     if [ -z "${CURRENT_RELEASE}" ]; then
687         if ! current_release; then
688             echo "${SCHEMA}: failure: cannot obtain current release"
689             continue
690         fi
691     else
692         if ! set_current_release "${CURRENT_RELEASE}"; then
693             echo "${SCHEMA}: failure: cannot set current release"
694             continue
695         fi
696     fi
697
698     # Check if the schema has already been installed
699     current_schema
700     RETRY=0
701     COMPARE=""
702     last_operation_status
703     last_status=$?
704     if [ $last_status -eq 0 ]; then
705         echo "Partial $LAST_OPERATION detected"
706         RETRY=1
707         if [ "${OPERATION}" == 'downgrade' ] && [ "${LAST_OPERATION}" == 'downgrade' ]; then
708             CURRENT_RELEASE="${LAST_FROM_VERSION}"
709             # greater than
710             COMPARE="gt"
711             echo "Downgrade will attempt to resume at $LAST_SCRIPT"
712         elif [ "${OPERATION}" == 'downgrade' ] && [ "${LAST_OPERATION}" == 'upgrade' ]; then
713             CURRENT_RELEASE="${LAST_TO_VERSION}"
714             # greater than or equal to
715             COMPARE="ge"
716             echo "Downgrade will attempt to resume before $LAST_SCRIPT"
717         elif [ "${OPERATION}" == 'upgrade' ] && [ "${LAST_OPERATION}" == 'upgrade' ]; then
718             CURRENT_RELEASE="${LAST_FROM_VERSION}"
719             # less than
720             COMPARE="lt"
721             echo "Upgrade will attempt to resume at $LAST_SCRIPT"
722         else
723             CURRENT_RELEASE="${LAST_TO_VERSION}"
724             # less than or equal
725             COMPARE="le"
726             echo "Upgrade will attempt to resume after $LAST_SCRIPT"
727         fi
728     fi
729
730     if [ -n "${INPUT_FROM_RELEASE}" ]; then
731         if [ "${CURRENT_RELEASE}" \> "${INPUT_FROM_RELEASE}" ] || [ "${CURRENT_RELEASE}" \< "${INPUT_FROM_RELEASE}" ]; then
732             echo "${SCHEMA}: On version ${CURRENT_RELEASE} cannot ${OPERATION} from ${INPUT_FROM_RELEASE}"
733             continue
734         else
735             CURRENT_RELEASE=${INPUT_FROM_RELEASE}
736         fi
737     fi
738
739     case ${OPERATION} in
740     upgrade)
741         if upgrade; then
742             echo "${SCHEMA}: OK: upgrade (${CURRENT_RELEASE})"
743         else
744             rc=1
745             echo "${SCHEMA}: failure: upgrade to release ${TARGET_UPGRADE_RELEASE} (${CURRENT_RELEASE})"
746         fi
747         ;;
748     downgrade)
749         if downgrade; then
750             echo "${SCHEMA}: OK: downgrade (${CURRENT_RELEASE})"
751         else
752             rc=1
753             echo "${SCHEMA}: failure: downgrade to release ${TARGET_DOWNGRADE_RELEASE} (${CURRENT_RELEASE})"
754         fi
755         ;;
756     version)
757         echo "${SCHEMA}: ${CURRENT_RELEASE}"
758         ;;
759     erase)
760         erase
761         ;;
762     report)
763         report
764         ;;
765     ok)
766         okay
767         ;;
768     esac
769
770 done
771 exit $rc