1698 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1698 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| source "$(dirname -- "$0")/lib/ulib/ulib" || exit 1
 | |
| urequire DEFAULTS install
 | |
| 
 | |
| function display_help() {
 | |
|     uecho "$scriptname: gérer les mises à jour sur une base de données
 | |
| 
 | |
| Les mises à jours sont dans un répertoire UPDATEDIR, qui contient un répertoire
 | |
| pour chaque base de données à gérer. Ces répertoires sont des DATABASEDIR. Les
 | |
| fichiers sql peuvent être placés dans le répertoire UPDATEDIR pour les mises à
 | |
| jour administratives, ou dans DATABASEDIR pour les mises à jour de la base de
 | |
| données.
 | |
| 
 | |
| Les fichiers sql peuvent contenir dans les premières lignes du fichier un tag
 | |
| @sqlmig sous forme de commentaire. On peut avoir:
 | |
| -- @sqlmig drop
 | |
|     identifie une suite de requêtes à exécuter pour supprimer la base de données
 | |
|     et recommencer à zéro
 | |
| -- @sqlmig create
 | |
|     identifie une suite de requêtes à exécuter pour créer la base de données.
 | |
| -- @sqlmig admin
 | |
|     identifie une mise à jour administrative. Les fichiers situés dans UPADTEDIR
 | |
|     sont automatiquement considérés comme des mises à jour administratives même
 | |
|     en l'absence de ce tag.
 | |
| 
 | |
| Les mises à jour administratives sont exécutées avec les paramètres du fichier
 | |
| my.cnf (resp. ora.conf) et sont typiquement utilisées pour créer les comptes
 | |
| utilisateurs pour la connexion à la base de données et leur attribuer des droits
 | |
| d'accès. Ces mises à jour sont exécutées sans sélectionner une base de données
 | |
| en particulier.
 | |
| 
 | |
| Les mises à jour utilisateurs sont exécutées avec les paramètres du fichier
 | |
| my.cnf (resp. ora.conf) augmenté du fichier my-DBNAME.cnf (res. ora-DBNAME.conf)
 | |
| Elles sont exécutées avec la base de données concernée sélectionnée.
 | |
| 
 | |
| Il y a deux modes d'exécution: prod ou devel. En mode prod, la suppression de
 | |
| base de données est interdite. De plus, tous les fichiers de mise à jour de la
 | |
| forme *.devel.sql sont ignorés. Cela permet de fignoler une mise à jour sans
 | |
| risquer de l'exécuter en production.
 | |
| 
 | |
| Les fichiers de la forme maint-*.sql sont ignorés sauf s'ils sont explicitement
 | |
| sélectionnés avec l'option -f ce qui permet de suivre les opérations de
 | |
| maintenance faites sur la base de données.
 | |
| 
 | |
| USAGE
 | |
|     $scriptname [options]
 | |
| 
 | |
| OPTIONS
 | |
|     -g, --admin-defaults-file ADMINDEFAULTS
 | |
|         Spécifier un fichier de configuration à utiliser pour se connecter à la
 | |
|         base de données pour les opérations de maintenance comme la création ou
 | |
|         la suppression de la base de données.
 | |
|         * Dans le mode MySQL, ce fichier est chargé en plus du fichier par
 | |
|           défaut my.cnf
 | |
|         * Dans le mode Oracle, ce fichier est chargé en plus du fichier par
 | |
|           défaut ora.conf.
 | |
|     -C, --defaults-file USERDEFAULTS
 | |
|         Spécifier un fichier de configuration à utiliser pour se connecter à la
 | |
|         base de données pour les opérations de mise à jour.
 | |
|         * Dans le mode MySQL, ce fichier est chargé en plus du fichier par
 | |
|           défaut my-DATABASE.cnf
 | |
|         * Dans le mode Oracle, ce fichier est chargé en plus du fichier par
 | |
|           défaut ora-DATABASE.conf.
 | |
|     -u, --user USER
 | |
|     -p, --password PASSWORD
 | |
|     -h, --host HOST
 | |
|     --port PORT
 | |
|     --socket SOCKET
 | |
|     --character-set CHARSET
 | |
|     -s, --oracle-sid ORACLE_SID
 | |
|     --nls-lang NLS_LANG
 | |
|         Spécifier les valeurs pour la connexion à la base de données. Les
 | |
|         options --host, --port et --socket ne sont valides que pour MySQL. Ces
 | |
|         valeurs remplacent les valeurs par défaut chargées depuis my.cnf
 | |
|         Les options --sid et --nls-lang ne sont valides que pour Oracle. Ces
 | |
|         valeurs remplacent les valeurs par défaut chargées depuis ora.conf
 | |
|     --suffix SUFFIX
 | |
|         Lors de la connexion à la base de données, toujours ajouter le suffixe
 | |
|         spécifié au nom de la base de données. Cette valeur peut être spécifiée
 | |
|         dans la section [sqlmig] du fichier my.cnf ou avec la variable SUFFIX
 | |
|         pour ora.conf
 | |
|     --csv2sql
 | |
|         Convertir les fichiers CSV en SQL. C'est la valeur par défaut. Ce
 | |
|         paramètre peut être spécifié dans my.cnf sous la forme
 | |
|             [sqlmig]
 | |
|             csv2sql=1
 | |
|         ou dans ora.conf
 | |
|             CSV2SQL=1
 | |
|         Pour le moment, cette conversion n'est supportée que pour MySQL. Tous
 | |
|         les fichiers de la forme [NUM]TABLE[-data].csv sont transformés en une
 | |
|         suite d'insertion dans la table TABLE. Une variante insère les données
 | |
|         dans la table après l'avoir vidée avec 'truncate table'. Les fichiers
 | |
|         doivent être de la forme [NUM]TABLE-data_truncate.csv
 | |
|     --csv-null VALUE
 | |
|         Lors de la conversion des fichiers .csv en .sql, considérer que VALUE
 | |
|         représente la valeur NULL. Par défaut, utiliser la chaine vide
 | |
|     --csv-null-empty
 | |
|     --csv-null-mysql
 | |
|     --csv-null-upper
 | |
|         Aliases pour --csv-null '', --csv-null '\\N' et --csv-null NULL respectivement
 | |
|     --no-csv2sql
 | |
|         Ne pas convertir les fichiers CSV en SQL. Ce paramètre peut être
 | |
|         spécifié dans my.cnf sous la forme
 | |
|             [sqlmig]
 | |
|             csv2sql=0
 | |
|         ou dans ora.conf
 | |
|             CSV2SQL=0
 | |
|     --load-data DEFAULT|LOCAL|SERVER
 | |
|         Si l'option --no-csv2sql est activée, spécifier le type de chargement
 | |
|         effectué pour les fichiers CSV.
 | |
|         * Avec LOCAL (la valeur par défaut), la directive 'load data local' est
 | |
|           utilisée. Cependant les erreurs éventuelles sont ignorées parce que le
 | |
|           serveur n'a pas de moyen pour arrêter la transmission des informations
 | |
|           par le client.
 | |
|         * Avec SERVER, la directive 'load data' est utilisée. Les erreurs
 | |
|           éventuelles sont affichées et arrêtent l'importation des données. Par
 | |
|           contre, le fichier doit être accessible par le serveur MySQL puisque
 | |
|           les données sont chargées directement par le serveur.
 | |
|           NB: avec MariaDB sur systemd, l'accès à /home, /root et /run/user est
 | |
|           désactivé par défaut. Pour pouvoir utiliser ce mode avec des fichiers
 | |
|           de l'utilisateur, il faut lancer ces commandes:
 | |
|               [ \$(id -u) == 0 ] && sudo= || sudo=sudo
 | |
|               \$sudo mkdir -p /etc/systemd/system/mariadb.service.d
 | |
|               \$sudo tee /etc/systemd/system/mariadb.service.d/dontprotecthome.conf <<<\$'[Service]\nProtectHome=false'
 | |
|               \$sudo systemctl daemon-reload
 | |
|         * Avec DEFAULT, utiliser SERVER si on communique avec le serveur MySQL
 | |
|           local (c'est à dire si host n'est pas spécifié ou vaut 127.*, ::1 ou
 | |
|           localhost). Sinon, utiliser LOCAL
 | |
|     --profile PROFILE
 | |
|     -P, --prod
 | |
|     -T, --test
 | |
|         Activer le profil spécifié. Les options -P et -T sont des aliases pour
 | |
|         les options --profile prod et --profile test respectivement.
 | |
|         Quand un profil est activé, les fichiers de configuration par défaut
 | |
|         deviennent respectivement \$PROFILE-my.cnf et \$PROFILE-ora.conf au lieu
 | |
|         de my.cnf et ora.conf. De plus, ces fichiers sont aussi recherchés dans
 | |
|         le répertoire /etc/sqlmig, en fonction du mode: en mode production, on
 | |
|         cherche d'abord dans /etc/sqlmig. En mode développement, on cherche
 | |
|         d'abord dans le répertoire local.
 | |
| 
 | |
|     --mysql
 | |
|     --oracle
 | |
|         Spécifier le type de base de données à gérer. Par défaut, on gère une
 | |
|         base de type mysql.
 | |
|         Avec le type oracle, il faut adapter la lecture de cette documentation:
 | |
|         à chaque fois que l'on parle de base de données, il s'agit en réalité de
 | |
|         gérer un utilisateur. La connexion à la base de données proprement dite
 | |
|         est configurée dans le fichier ora.conf
 | |
|     -0, --init
 | |
|         Créer les fichiers initiaux pour gérer une base de données. Cette option
 | |
|         est utilisée pour le développement
 | |
|     -e, --export DESTUPDATEDIR
 | |
|         Exporter les définitions de bases de données et mises à jour du
 | |
|         répertoire courant vers le répertoire DESTUPDATEDIR
 | |
|     -c, --connect
 | |
|         Se connecter avec le client natif (mysql ou sqlplus) sur la base de
 | |
|         données courante.
 | |
|     -r, --restore-test
 | |
|         Restaurer une sauvegarde d'une base de production sur la test. Cette
 | |
|         option n'est (actuellement) supportée que pour MySQL.
 | |
|         L'argument attendu est un fichier de sauvegarde DATABASE.sql[.gz]
 | |
|         effectué avec la commande
 | |
|             mysqldump --databases --add-drop-database DATABASE
 | |
|         Dans le fichier spécifié, on remplace toutes les occurences de DATABASE
 | |
|         par DATABASE_test, ensuite on lance (re)création de la base de données
 | |
|             mysql <DATABASE_test.sql
 | |
|     --update-all
 | |
|         Mettre à jour la base de données. C'est l'option par défaut
 | |
|     -t, --updatedir UPDATEDIR
 | |
|         Spécifier le répertoire qui contient les répertoires de mises à jour
 | |
|         pour chaque base de données.
 | |
|     -d, --databasedir DATABASEDIR
 | |
|         Spécifier le répertoire qui contient les mises à jour à appliquer pour
 | |
|         une base de données spécifique. Le nom de la base de données à gérer est
 | |
|         déterminé à partir du nom du répertoire. Si cette option n'est pas
 | |
|         spécifiée, tous les répertoires de base de données de UPDATEDIR sont
 | |
|         considérés.
 | |
|     -b, --database DATABASE
 | |
|         Spécifier le nom de la base de données. En principe le nom de la base de
 | |
|         données est calculé à partir du nom du répertoire DATABASEDIR. Cette
 | |
|         option peut être utilisée par exemple pour créer une base de test à
 | |
|         partir des définitions d'une base de prod.
 | |
|         Notez que le suffixe spécifié avec l'option --suffix est toujours
 | |
|         rajouté au nom de la base de données.
 | |
|     -f, --update-one UPDATES...
 | |
|         Forcer l'application des mises à jour spécifiées. Ne pas mettre à jour
 | |
|         l'état des mises à jour installées.
 | |
|         Important: Avec cette option, tout se passe comme si les seuls fichiers
 | |
|         existant sont ceux spécifiés. Par exemple, quel que soit l'ordre dans
 | |
|         lequel les fichiers sont spécifiés, ils sont évalués dans l'ordre
 | |
|         alphanumérique et sont ignorés s'ils n'ont pas l'extension .sql
 | |
| 
 | |
|     -n, --fake
 | |
|         Ne pas faire les mises à jour, afficher simplement ce qui serait fait
 | |
|     --force, --continue-on-error
 | |
|         Ne pas s'arrêter en cas d'erreur de mise à jour
 | |
|     --no-data-csv
 | |
|         Ne pas procéder à la conversion des fichiers CSV en SQL
 | |
|     --force-data-csv
 | |
|         Forcer la conversion des fichiers CSV en SQL. Par défaut, la conversion
 | |
|         n'est faite que si le fichier csv est plus récent que le fichier sql
 | |
|         correspondant.
 | |
|     --devel-mode
 | |
|         Activer le mode développement. Ce mode est automatiquement activé si
 | |
|         l'utilisateur courant n'est pas root. La suppression des bases de
 | |
|         données n'est autorisée qu'en mode développement
 | |
|     -Z, --recreate
 | |
|         Supprimer la base de données puis la recréer et appliquer les mises à
 | |
|         jour.
 | |
|     --drop-only
 | |
|         Supprimer la base de données uniquement. Ne pas la recréer.
 | |
|     --create-only
 | |
|         Créer la base de données uniquement. Ne pas appliquer les mises à jour"
 | |
| }
 | |
| 
 | |
| function mconf_get() {
 | |
|     local cnf="$1" section="$2" name="$3"
 | |
|     awkrun <"$cnf" section="$section" name="$name" '
 | |
|     BEGIN { in_section = 0 }
 | |
|     !in_section && $0 == "[" section "]" { in_section = 1; next }
 | |
|     in_section && $0 == "[" section "]" { in_section = 0; next }
 | |
|     in_section && $0 ~ "^" name " *=" {
 | |
|         gsub(/^[^=]*= */, "")
 | |
|         print
 | |
|         exit
 | |
|     }
 | |
|     '
 | |
| }
 | |
| 
 | |
| function __check_devel_dir() {
 | |
|     # $1 = P (le préfixe)
 | |
|     # parentdir et cwd doivent être définis. initialiser le cas échéant la
 | |
|     # variable updatedir
 | |
|     local updatedir dbdir
 | |
|     if [ "${parentdir%/$1}" != "$parentdir" ]; then
 | |
|         # On est dans un répertoire de la forme P/$1/DB, autosélectioner P/$1
 | |
|         upvar updatedir "$parentdir"
 | |
|         upvar dbdir "$cwd"
 | |
|         return 0
 | |
|     elif [ "${cwd%/$1}" != "$cwd" ]; then
 | |
|         # On est dans un répertoire de la forme P/$1, autosélectioner P/$1
 | |
|         upvar updatedir "$cwd"
 | |
|         return 0
 | |
|     elif [ -d "$cwd/$1" ]; then
 | |
|         # On est dans un répertoire P tel que P/$1 existe, autosélectioner P/$1
 | |
|         upvar updatedir "$cwd/$1"
 | |
|         return 0
 | |
|     fi
 | |
|     return 1
 | |
| }
 | |
| function __check_mysql_prod_dir() {
 | |
|     # parentdir et cwd doivent être définis
 | |
|     local dir updatedir dbdir
 | |
|     if [ "${parentdir%/updates}" != "$parentdir" ]; then
 | |
|         # Si on est dans un répertoire de la forme P/updates/DB, alors
 | |
|         # sélectioner P/updates si P contient le marqueur .mysqld-update
 | |
|         dir="$parentdir"
 | |
|         dbdir="$cwd"
 | |
|     elif [ -d "$cwd/updates" ]; then
 | |
|         # Si on est dans un répertoire P tel que P/updates existe, alors
 | |
|         # sélectioner P/updates si P contient le marqueur .mysqld-update
 | |
|         dir="$cwd/updates"
 | |
|     fi
 | |
|     if [ -n "$dir" -a -f "$(dirname -- "$dir")/.mysqld-update" ]; then
 | |
|         upvar updatedir "$dir"
 | |
|         [ -n "$dbdir" ] && upvar dbdir "$dbdir"
 | |
|         return 0
 | |
|     fi
 | |
|     return 1
 | |
| }
 | |
| 
 | |
| function find_mysqldupdatedir() {
 | |
|     # en commençant à partir du répertoire $1 qui vaut par défaut le répertoire
 | |
|     # courant, chercher un répertoire contenant le fichier témoin .mysqld-update
 | |
|     local dir="$1" origdir
 | |
|     [ -n "$dir" ] || dir="$(pwd)"
 | |
|     setx dir=abspath "$dir"
 | |
|     origdir="$dir"
 | |
| 
 | |
|     while true; do
 | |
|         if [ -f "$dir/.mysqld-update" ]; then
 | |
|             echo "$dir"
 | |
|             return 0
 | |
|         fi
 | |
|         if [ -z "$dir" -o "$dir" == / -o "$dir" == "$HOME" ]; then
 | |
|             echo "$origdir"
 | |
|             return 1
 | |
|         fi
 | |
|         setx dir=dirname -- "$dir"
 | |
|     done
 | |
| }
 | |
| function check_mysqldupdatedir() {
 | |
|     local exportdir="$1"
 | |
|     [ -f "$exportdir/.mysqld-update" ] || die "$(ppath "$exportdir"): n'est pas un répertoire mysqld-update"
 | |
| }
 | |
| 
 | |
| function have_tag() {
 | |
|     # tester si le fichier $2 a le tag "@sqlmig $1"
 | |
|     <"$2" awk '{print; if ($0 == "") exit}' | quietgrep '^--  *@sqlmig  *'"$1"' *$'
 | |
| }
 | |
| 
 | |
| function abort_on_error() {
 | |
|     [ -z "$force" ] && die "$@"
 | |
| }
 | |
| 
 | |
| function ensure_dbtype() {
 | |
|     local dir="$1" type="$2"
 | |
|     if [ "$type" == auto ]; then
 | |
|         if [ -f "$dir/my.cnf" ]; then
 | |
|             dbtype=mysql
 | |
|         elif [ -f "$dir/ora.conf" ]; then
 | |
|             dbtype=oracle
 | |
|         else
 | |
|             die "Vous devez spécifier le type --mysql ou --oracle"
 | |
|         fi
 | |
|     else
 | |
|         dbtype="$type"
 | |
|     fi
 | |
| }
 | |
| function ensure_dbmode() {
 | |
|     local dbtype="$1" mode="$2"
 | |
|     if [ "$mode" == auto ]; then
 | |
|         local profile_mode
 | |
|         if [ -n "$profile" ]; then
 | |
|             profile_mode="${profile}_PROFILE_MODE"
 | |
|             profile_mode="${!profile_mode}"
 | |
|         fi
 | |
|         if [ -n "$profile_mode" ]; then
 | |
|             dbmode="$profile_mode"
 | |
|         elif [ "$dbtype" == mysql ]; then
 | |
|             is_root && dbmode=prod || dbmode=devel
 | |
|         else
 | |
|             dbmode=prod
 | |
|         fi
 | |
|     else
 | |
|         dbmode="$mode"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function set_dbdirs() {
 | |
|     if [ -n "$dbdir" ]; then
 | |
|         dbdirs=("$dbdir")
 | |
|     elif [ -z "$updatedir" ]; then
 | |
|         array_lsfiles files . "*.sql"
 | |
|         if [ ${#files[*]} -gt 0 ]; then
 | |
|             enote "Autosélection répertoire courant"
 | |
|             dbdir="$cwd"
 | |
|             dbdirs=("$dbdir")
 | |
|         else
 | |
|             die "Vous devez spécifier l'option -b"
 | |
|         fi
 | |
|     elif [ -n "$dbname" ]; then
 | |
|         dbdirs=("$updatedir/$dbname")
 | |
|     else
 | |
|         array_lsdirs dbdirs "$updatedir"
 | |
|     fi
 | |
| 
 | |
|     if [ -n "$dbname" -a ${#dbdirs[*]} -gt 1 ]; then
 | |
|         die "Avec l'option -n, une seule base de données doit être spécifiée"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function fix_csv2sql() {
 | |
|     if [ -z "$csv2sql" ]; then
 | |
|         # valeur par défaut
 | |
|         csv2sql=1
 | |
|     elif is_yes "$csv2sql"; then
 | |
|         csv2sql=1
 | |
|     elif is_no "$csv2sql"; then
 | |
|         csv2sql=0
 | |
|     fi
 | |
| }
 | |
| function fix_csv_null() {
 | |
|     # si csv_null a une valeur vide, c'est déjà la valeur par défaut
 | |
|     case "$csv_null" in
 | |
|     empty) csv_null=;;
 | |
|     mysql) csv_null='\N';;
 | |
|     upper) csv_null=NULL;;
 | |
|     esac
 | |
| }
 | |
| function fix_load_data() {
 | |
|     if [ -z "$load_data" ]; then
 | |
|         # valeur par défaut
 | |
|         load_data=local
 | |
|     else
 | |
|         case "${load_data,,}" in
 | |
|         default|d*) load_data=default;;
 | |
|         local|l*) load_data=local;;
 | |
|         server|s*) load_data=server;;
 | |
|         esac
 | |
|     fi
 | |
|     if [ "$load_data" == default ]; then
 | |
|         case "$host" in
 | |
|         ""|localhost|127.*|::1) load_data=server;;
 | |
|         *) load_data=local;;
 | |
|         esac
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function get_csvinfo() {
 | |
|     # afficher les informations sur un fichier csv: nom de la table, et s'il
 | |
|     # faut faire un truncate
 | |
|     local csvname="$(basename -- "$1")"
 | |
|     local script='{
 | |
|   truncate = ($0 ~ /-data_truncate(.devel)?.csv$/)? "1": ""
 | |
|   sub(/^.*\//, "")
 | |
|   sub(/^(([A-Z][-.A-Z0-9]*[0-9]-?)|([0-9][-.0-9]*-?))/, "")
 | |
|   sub(/\.csv$/, "")
 | |
|   sub(/\.devel$/, "")
 | |
|   sub(/-data(_[a-z]+*)?$/, "")
 | |
|   print "truncate=" truncate
 | |
|   gsub(/'\''/, "'\'\\\\\'\''")
 | |
|   print "table='\''" $0 "'\''"
 | |
| }'
 | |
|     awk "$script" <<<"$csvname"
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| # MySQL
 | |
| 
 | |
| function get_mysql_admindb() { echo "sqlmig_admin_db_"; }
 | |
| function get_mysql_admintb() { echo "sqlmig_updates_"; }
 | |
| function get_mysql_usertb() { echo "${1}_updates_"; }
 | |
| 
 | |
| function mysql_ve() {
 | |
|     #local r; set -x #DEBUG
 | |
|     mysql "${@:3}" ${2:+-D "$2"} ${1:+-e "$1"}
 | |
|     #r=$?; set +x; return $r #DEBUG
 | |
| }
 | |
| function mysql_user_ve() {
 | |
|     mysql_ve "$1" "$dbname" "${userargs[@]}" "${mysqlargs[@]}" "${@:2}"
 | |
| }
 | |
| function mysql_user_qe() {
 | |
|     if show_debug; then mysql_user_ve "$@"
 | |
|     elif show_verbose; then mysql_user_ve "$@" >/dev/null
 | |
|     else mysql_user_ve "$@" >&/dev/null
 | |
|     fi
 | |
| }
 | |
| function mysql_admin_ve() {
 | |
|     mysql_ve "$1" "$2" "${adminargs[@]}" "${mysqlargs[@]}" "${@:3}"
 | |
| }
 | |
| function mysql_admin_qe() {
 | |
|     if show_debug; then mysql_admin_ve "$@"
 | |
|     elif show_verbose; then mysql_admin_ve "$@" >/dev/null
 | |
|     else mysql_admin_ve "$@" >&/dev/null
 | |
|     fi
 | |
| }
 | |
| function mysql_tbconf() {
 | |
|     [ -n "$fake" ] && return
 | |
| 
 | |
|     # s'assurer que la table des mises à jour existe
 | |
|     local dbname="$1" tb="$2"
 | |
| 
 | |
|     if [ -z "$dbname" ]; then
 | |
|         # admin
 | |
|         setx dbname=get_mysql_admindb
 | |
|         if ! mysql_admin_qe "select 1" "$dbname"; then
 | |
|             mysql_admin_qe "create database $dbname"
 | |
|         fi
 | |
|         [ -n "$tb" ] || setx tb=get_mysql_admintb "$dbname"
 | |
|         if ! mysql_admin_qe "select count(*) from $tb" "$dbname"; then
 | |
|             mysql_admin_qe "create table $tb (
 | |
|  name varchar(128) not null primary key
 | |
| ,tem_done int(1)
 | |
| ,date_start datetime
 | |
| ,date_done datetime
 | |
| )" "$dbname" || die "create table $tb"
 | |
|         fi
 | |
|     else
 | |
|         # user
 | |
|         [ -n "$tb" ] || setx tb=get_mysql_usertb "$dbname"
 | |
|         if ! mysql_user_qe "select count(*) from $tb"; then
 | |
|             mysql_user_qe "create table $tb (
 | |
|  name varchar(128) not null primary key
 | |
| ,tem_done int(1)
 | |
| ,date_start datetime
 | |
| ,date_done datetime
 | |
| )" || die "create table $tb"
 | |
|         fi
 | |
|     fi
 | |
| }
 | |
| function mysql_get_done() {
 | |
|     local name="$1" dbname="$2" tb="$3"
 | |
|     if [ -z "$dbname" ]; then
 | |
|         # admin
 | |
|         setx dbname=get_mysql_admindb
 | |
|         [ -n "$tb" ] || setx tb=get_mysql_admintb "$dbname"
 | |
|         mysql_admin_ve "select name from $tb where name = '$name' and tem_done = 1" "$dbname" -N
 | |
|     else
 | |
|         # user
 | |
|         [ -n "$tb" ] || setx tb=get_mysql_usertb "$dbname"
 | |
|         mysql_user_ve "select name from $tb where name = '$name' and tem_done = 1" -N
 | |
|     fi
 | |
| }
 | |
| function mysql_before_update() {
 | |
|     local dbname="$1" tb="$2"
 | |
|     if [ -z "$dbname" ]; then
 | |
|         # admin
 | |
|         setx dbname=get_mysql_admindb
 | |
|         [ -n "$tb" ] || setx tb=get_mysql_admintb "$dbname"
 | |
|         mysql_admin_ve "insert into $tb (name, tem_done, date_start) values ('$name', 0, sysdate()) on duplicate key update tem_done = 0, date_start = sysdate(), date_done = null" "$dbname"
 | |
|     else
 | |
|         # user
 | |
|         [ -n "$tb" ] || setx tb=get_mysql_usertb "$dbname"
 | |
|         mysql_user_ve "insert into $tb (name, tem_done, date_start) values ('$name', 0, sysdate()) on duplicate key update tem_done = 0, date_start = sysdate(), date_done = null"
 | |
|     fi
 | |
| }
 | |
| function mysql_after_update() {
 | |
|     local dbname="$1" tb="$2"
 | |
|     if [ -z "$dbname" ]; then
 | |
|         # admin
 | |
|         setx dbname=get_mysql_admindb
 | |
|         [ -n "$tb" ] || setx tb=get_mysql_admintb "$dbname"
 | |
|         mysql_admin_ve "update $tb set tem_done = 1, date_done = sysdate() where name = '$name'" "$dbname"
 | |
|     else
 | |
|         # user
 | |
|         [ -n "$tb" ] || setx tb=get_mysql_usertb "$dbname"
 | |
|         mysql_user_ve "update $tb set tem_done = 1, date_done = sysdate() where name = '$name'"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function mysql_get_defaults() {
 | |
|     local dir="$1"
 | |
|     if [ -n "$profile" ]; then
 | |
|         if [ "$dbmode" == devel ]; then
 | |
|             if [ -f "$dir/${profile}-my.cnf" ]; then
 | |
|                 echo "$dir/${profile}-my.cnf"; return
 | |
|             elif [ -f "$PROFILEDIR/${profile}-my.cnf" ]; then
 | |
|                 echo "$PROFILEDIR/${profile}-my.cnf"; return
 | |
|             fi
 | |
|         else
 | |
|             if [ -f "$PROFILEDIR/${profile}-my.cnf" ]; then
 | |
|                 echo "$PROFILEDIR/${profile}-my.cnf"; return
 | |
|             elif [ -f "$dir/${profile}-my.cnf" ]; then
 | |
|                 echo "$dir/${profile}-my.cnf"; return
 | |
|             fi
 | |
|         fi
 | |
|     fi
 | |
|     echo "$dir/my.cnf"
 | |
| }
 | |
| function mysql_set_adminargs() {
 | |
|     local dir="$1" defaults
 | |
|     adminargs=()
 | |
|     setx defaults=mysql_get_defaults "$dir"
 | |
|     if [ -f "$defaults" ]; then
 | |
|         array_add adminargs --defaults-file="$defaults"
 | |
|         if [ -n "$admindefaults" ]; then
 | |
|             array_add adminargs --defaults-extra-file="$admindefaults"
 | |
|         fi
 | |
|     elif [ -n "$admindefaults" ]; then
 | |
|         array_add adminargs --defaults-file="$admindefaults"
 | |
|     fi
 | |
|     [ ${#adminargs[*]} -gt 0 ] || array_add adminargs --default-character-set utf8
 | |
| }
 | |
| function mysql__mconf_get() {
 | |
|     local defaults="$1" tmp
 | |
|     if [ -n "$set_suffix" ]; then
 | |
|         setx tmp=mconf_get "$defaults" sqlmig suffix
 | |
|         [ -n "$tmp" ] && suffix="$tmp"
 | |
|     fi
 | |
|     if [ -n "$set_csv2sql" ]; then
 | |
|         setx tmp=mconf_get "$defaults" sqlmig csv2sql
 | |
|         [ -n "$tmp" ] && {
 | |
|             csv2sql="$tmp"
 | |
|             fix_csv2sql
 | |
|         }
 | |
|     fi
 | |
|     if [ -n "$set_csv_null" ]; then
 | |
|         setx tmp=mconf_get "$defaults" sqlmig csv_null
 | |
|         [ -n "$tmp" ] && {
 | |
|             csv_null="$tmp"
 | |
|             fix_csv_null
 | |
|         }
 | |
|     fi
 | |
|     if [ -n "$set_load_data" ]; then
 | |
|         if [ -z "$host" ]; then
 | |
|             # load_data==default requière host
 | |
|             setx host=mconf_get "$defaults" client host
 | |
|         fi
 | |
|         setx tmp=mconf_get "$defaults" sqlmig load-data
 | |
|         [ -n "$tmp" ] && {
 | |
|             load_data="$tmp"
 | |
|             fix_load_data
 | |
|         }
 | |
|     fi
 | |
| }
 | |
| function mysql_set_userargs() {
 | |
|     local dir="$1" dbname="$2" defaults
 | |
|     local set_suffix set_csv2sql set_csv_null set_load_data
 | |
|     userargs=()
 | |
|     setx defaults=mysql_get_defaults "$dir"
 | |
|     [ -z "$suffix" ] && set_suffix=1
 | |
|     [ -z "$csv2sql" ] && set_csv2sql=1
 | |
|     [ -z "$csv_null" ] && set_csv_null=1
 | |
|     [ -z "$load_data" ] && set_load_data=1
 | |
|     if [ -f "$defaults" ]; then
 | |
|         array_add userargs --defaults-file="$defaults"
 | |
|         mysql__mconf_get "$defaults"
 | |
|         if [ -n "$userdefaults" ]; then
 | |
|             array_add userargs --defaults-extra-file="$userdefaults"
 | |
|             mysql__mconf_get "$userdefaults"
 | |
|         elif [ -f "$dir/my-${dbname}.cnf" ]; then
 | |
|             array_add userargs --defaults-extra-file="$dir/my-${dbname}.cnf"
 | |
|             mysql__mconf_get "$dir/my-${dbname}.cnf"
 | |
|         fi
 | |
|     elif [ -n "$userdefaults" ]; then
 | |
|         array_add userargs --defaults-file="$userdefaults"
 | |
|         mysql__mconf_get "$userdefaults"
 | |
|     elif [ -f "$dir/my-${dbname}.cnf" ]; then
 | |
|         array_add userargs --defaults-file="$dir/my-${dbname}.cnf"
 | |
|         mysql__mconf_get "$dir/my-${dbname}.cnf"
 | |
|     fi
 | |
|     [ ${#userargs[*]} -gt 0 ] || array_add userargs --default-character-set utf8
 | |
|     # initialiser les valeurs par défaut
 | |
|     fix_csv2sql
 | |
|     fix_csv_null
 | |
|     fix_load_data
 | |
| }
 | |
| function mysql_set_mysqlargs() {
 | |
|     mysqlargs=()
 | |
|     [ -n "$user" ] && array_add mysqlargs -u "$user"
 | |
|     [ -n "$pwset" ] && array_add mysqlargs -p"$password"
 | |
|     [ -n "$host" ] && array_add mysqlargs -h "$host"
 | |
|     [ -n "$port" ] && array_add mysqlargs -P "$port"
 | |
|     [ -n "$socket" ] && array_add mysqlargs -S "$socket"
 | |
|     [ -n "$charset" ] && array_add mysqlargs --default-character-set "$charset"
 | |
|     [ -n "$force" ] && array_add mysqlargs -f
 | |
|     array_add mysqlargs -B
 | |
| }
 | |
| MYSQL_ADMIN_CONF_DONE=
 | |
| function mysql_admin_update() {
 | |
|     local name="$1" update="$2" updateone="$3" done
 | |
|     if [ -z "$updateone" ]; then
 | |
|         if [ -z "$MYSQL_ADMIN_CONF_DONE" ]; then
 | |
|             MYSQL_ADMIN_CONF_DONE=1
 | |
|             mysql_tbconf
 | |
|         fi
 | |
|         if ! setx done=mysql_get_done "$name"; then
 | |
|             [ -n "$fake" ] || die
 | |
|         fi
 | |
|         [ -n "$done" ] && return
 | |
|     fi
 | |
| 
 | |
|     estep "$name"
 | |
|     [ -n "$fake" ] && return
 | |
| 
 | |
|     if [ -z "$updateone" ]; then
 | |
|         mysql_before_update || die
 | |
|     fi
 | |
|     cat "$update" | mysql_admin_ve || abort_on_error
 | |
|     if [ -z "$updateone" ]; then
 | |
|         mysql_after_update || die
 | |
|     fi
 | |
| }
 | |
| function mysql_user_update() {
 | |
|     local name="$1" update="$2" dbname="$3" updateone="$4" done
 | |
|     if [ -z "$updateone" ]; then
 | |
|         if ! setx done=mysql_get_done "$name" "$dbname"; then
 | |
|             [ -n "$fake" ] || die
 | |
|         fi
 | |
|         [ -n "$done" ] && return
 | |
|     fi
 | |
| 
 | |
|     estep "$name"
 | |
|     [ -n "$fake" ] && return
 | |
| 
 | |
|     if [ -z "$updateone" ]; then
 | |
|         mysql_before_update "$dbname" || die
 | |
|     fi
 | |
|     if [[ "$update" == *.sql ]]; then
 | |
|         # SQL
 | |
|         cat "$update" | mysql_user_ve || abort_on_error
 | |
|     else
 | |
|         # CSV
 | |
|         local truncate table local sql
 | |
|         eval "$(get_csvinfo "$update")"
 | |
|         [ -n "$truncate" ] && sql="truncate table $table;"
 | |
|         [ "$load_data" == local ] && local=1 || local=
 | |
|         sql="${sql}load data${local:+ local} infile '$update' into table \`$table\`
 | |
|  character set 'utf8'
 | |
|  fields terminated by ','
 | |
|  optionally enclosed by '\\\"'
 | |
|  escaped by '\\\\'
 | |
|  lines terminated by '\\n'
 | |
|  starting by ''
 | |
|  ignore 1 lines
 | |
|  ($(<"$update" awk '{ print; exit }'));"
 | |
|         echo "$sql" | mysql_user_ve || abort_on_error
 | |
|     fi
 | |
|     if [ -z "$updateone" ]; then
 | |
|         mysql_after_update "$dbname" || die
 | |
|     fi
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| # Oracle
 | |
| 
 | |
| function get_oracle_admindb() { echo "sqlmig_admin_db_"; }
 | |
| function get_oracle_admintb() { echo "sqlmig_updates_"; }
 | |
| function get_oracle_usertb() { echo "${1}_updates_"; }
 | |
| 
 | |
| function oracle_sqlplus() {
 | |
|     # lancer sqlplus sans affichage superflu, et spooler vers $SQLMIGLOG
 | |
|     #local r; set -x #DEBUG
 | |
|     echo "\
 | |
| set pagesize 0
 | |
| set feedback off
 | |
| set linesize 8192
 | |
| set tab off
 | |
| whenever oserror exit failure
 | |
| whenever sqlerror exit sql.sqlcode
 | |
| spool '$SQLMIGLOG' append" >"$OPDIR/login.sql"
 | |
|     local connect="$1@$ORACLE_SID" sysdba="$2"; shift; shift
 | |
|     ORACLE_PATH="$OPDIR" sqlplus -S "$connect" ${sysdba:+as sysdba} "$@"
 | |
|     #r=$?; set +x; return $r #DEBUG
 | |
| }
 | |
| function qe() {
 | |
|     # lancer la commande $@: si elle retourne un code d'erreur, afficher le
 | |
|     # résultat de la commande sur stderr si on est en mode verbeux, sinon ne
 | |
|     # rien afficher
 | |
|     local r output
 | |
|     output="$("$@")"; r=$?
 | |
|     if [ ${#output} -gt 0 ]; then
 | |
|         show_verbose && echo "$output" 1>&2
 | |
|     fi
 | |
|     return $r
 | |
| }
 | |
| 
 | |
| function oracle_admin_query() {
 | |
|     # lancer sqlplus avec la connexion admin
 | |
|     oracle_sqlplus "$ADMINCONNECT" "$ADMINDBA" "$@"
 | |
| }
 | |
| function oracle_admin_ve() {
 | |
|     # lancer une requête admin, ne pas masquer le résultat
 | |
|     if [ $# -gt 0 ]; then
 | |
|         show_debug && edebug "query: $*"
 | |
|         oracle_admin_query <<<"$*"
 | |
|     else
 | |
|         oracle_admin_query
 | |
|     fi
 | |
| }
 | |
| function oracle_admin_qe() {
 | |
|     # lancer une requête admin en masquant le résultat
 | |
|     if [ $# -gt 0 ]; then
 | |
|         show_debug && edebug "query: $*"
 | |
|         qe oracle_admin_query <<<"$*"
 | |
|     else
 | |
|         qe oracle_admin_query
 | |
|     fi
 | |
| }
 | |
| function oracle_admin_ne() {
 | |
|     # lancer une requête admin et retourner vrai si elle affiche un résultat
 | |
|     if [ $# -gt 0 ]; then
 | |
|         show_debug && edebug "query: $*"
 | |
|         [ -n "$(oracle_admin_query <<<"$*")" ]
 | |
|     else
 | |
|         [ -n "$(oracle_admin_query)" ]
 | |
|     fi
 | |
| }
 | |
| function oracle_admin_have_user() {
 | |
|     # tester en mode admin si le user $1 existe
 | |
|     oracle_admin_ne "select username from all_users where username = '${1^^}';"
 | |
| }
 | |
| function oracle_admin_have_table() {
 | |
|     # tester en mode admin si le table $1 existe (avec éventuellement le owner $2)
 | |
|     local sql="select table_name from all_tables where table_name = '${1^^}'"
 | |
|     [ -n "$2" ] && sql="$sql and owner = '${2^^}'"
 | |
|     oracle_admin_ne "$sql;"
 | |
| }
 | |
| 
 | |
| function oracle_user_query() {
 | |
|     # lancer sqlplus avec la connexion user
 | |
|     oracle_sqlplus "$USERCONNECT" "$USERDBA" "$@"
 | |
| }
 | |
| function oracle_user_ve() {
 | |
|     # lancer une requête user, ne pas masquer le résultat
 | |
|     if [ $# -gt 0 ]; then
 | |
|         show_debug && edebug "query: $*"
 | |
|         oracle_user_query <<<"$*"
 | |
|     else
 | |
|         oracle_user_query
 | |
|     fi
 | |
| }
 | |
| function oracle_user_qe() {
 | |
|     # lancer une requête user en masquant le résultat
 | |
|     if [ $# -gt 0 ]; then
 | |
|         show_debug && edebug "query: $*"
 | |
|         qe oracle_user_query <<<"$*"
 | |
|     else
 | |
|         qe oracle_user_query
 | |
|     fi
 | |
| }
 | |
| function oracle_user_ne() {
 | |
|     # lancer une requête user et retourner vrai si elle affiche un résultat
 | |
|     if [ $# -gt 0 ]; then
 | |
|         show_debug && edebug "query: $*"
 | |
|         [ -n "$(oracle_user_query <<<"$*")" ]
 | |
|     else
 | |
|         [ -n "$(oracle_user_query)" ]
 | |
|     fi
 | |
| }
 | |
| function oracle_user_have_user() {
 | |
|     # tester en mode user si le user $1 existe
 | |
|     oracle_user_ne "select username from all_users where username = '${1^^}';"
 | |
| }
 | |
| function oracle_user_have_table() {
 | |
|     # tester en mode user si le table $1 existe (avec éventuellement le owner $2)
 | |
|     local sql="select table_name from all_tables where table_name = '${1^^}'"
 | |
|     [ -n "$2" ] && sql="$sql and owner = '${2^^}'"
 | |
|     oracle_user_ne "$sql;"
 | |
| }
 | |
| 
 | |
| function oracle_tbconf() {
 | |
|     [ -n "$fake" ] && return
 | |
| 
 | |
|     # s'assurer que la table des mises à jour existe
 | |
|     local dbname="$1" tb="$2"
 | |
|     if [ -z "$dbname" ]; then
 | |
|         # admin
 | |
|         setx dbname=get_oracle_admindb
 | |
|         #if ! oracle_admin_have_user "$dbname"; then
 | |
|         #    oracle_admin_ve "create user $dbname; grant connect to $dbname;"
 | |
|         #fi
 | |
|         [ -n "$tb" ] || setx tb=get_oracle_admintb "$dbname"
 | |
|         local owner="${ADMINCONNECT%%/*}"
 | |
|         [ -n "owner" ] || owner=system
 | |
|         if ! oracle_admin_have_table "$tb" "$owner"; then
 | |
|             oracle_admin_ve "create table $tb (
 | |
|  name varchar(128) not null primary key
 | |
| ,tem_done number(1)
 | |
| ,date_start timestamp
 | |
| ,date_done timestamp
 | |
| );" || die "create table $tb"
 | |
|         fi
 | |
|     else
 | |
|         # user
 | |
|         [ -n "$tb" ] || setx tb=get_oracle_usertb "$dbname"
 | |
|         local owner="${USERCONNECT%%/*}"
 | |
|         [ -n "owner" ] || owner=system
 | |
|         if ! oracle_user_have_table "$tb" "$owner"; then
 | |
|             oracle_user_ve "create table $tb (
 | |
|  name varchar(128) not null primary key
 | |
| ,tem_done number(1)
 | |
| ,date_start timestamp
 | |
| ,date_done timestamp
 | |
| );" || die "create table $tb"
 | |
|         fi
 | |
|     fi
 | |
| }
 | |
| function oracle_get_done() {
 | |
|     # afficher le nom d'une mise à jour si elle a été appliquée
 | |
|     local name="$1" dbname="$2" tb="$3"
 | |
|     if [ -z "$dbname" ]; then
 | |
|         # admin
 | |
|         setx dbname=get_oracle_admindb
 | |
|         [ -n "$tb" ] || setx tb=get_oracle_admintb "$dbname"
 | |
|         oracle_admin_ve "select name from $tb where name = '$name' and tem_done = 1;"
 | |
|     else
 | |
|         # user
 | |
|         [ -n "$tb" ] || setx tb=get_oracle_usertb "$dbname"
 | |
|         oracle_user_ve "select name from $tb where name = '$name' and tem_done = 1;"
 | |
|     fi
 | |
| }
 | |
| function oracle_before_update() {
 | |
|     # préparer l'exécution d'une mise à jour
 | |
|     local dbname="$1" tb="$2"
 | |
|     if [ -z "$dbname" ]; then
 | |
|         # admin
 | |
|         setx dbname=get_oracle_admindb
 | |
|         [ -n "$tb" ] || setx tb=get_oracle_admintb "$dbname"
 | |
|         oracle_admin_ve "\
 | |
| merge into $tb d
 | |
| using (select '$name' name from dual) s
 | |
| on (d.name = s.name)
 | |
| when matched then update set d.tem_done = 0, d.date_start = sysdate, d.date_done = null
 | |
| when not matched then insert (name, tem_done, date_start) values ('$name', 0, sysdate);
 | |
| commit;"
 | |
|     else
 | |
|         # user
 | |
|         [ -n "$tb" ] || setx tb=get_oracle_usertb "$dbname"
 | |
|         oracle_user_ve "\
 | |
| merge into $tb d
 | |
| using (select '$name' name from dual) s
 | |
| on (d.name = s.name)
 | |
| when matched then update set d.tem_done = 0, d.date_start = sysdate, d.date_done = null
 | |
| when not matched then insert (name, tem_done, date_start) values ('$name', 0, sysdate);
 | |
| commit;"
 | |
|     fi
 | |
| }
 | |
| function oracle_after_update() {
 | |
|     # valider l'exécution d'une mise à jour
 | |
|     local dbname="$1" tb="$2"
 | |
|     if [ -z "$dbname" ]; then
 | |
|         # admin
 | |
|         setx dbname=get_oracle_admindb
 | |
|         [ -n "$tb" ] || setx tb=get_oracle_admintb "$dbname"
 | |
|         oracle_admin_ve "\
 | |
| update $tb set tem_done = 1, date_done = sysdate where name = '$name';
 | |
| commit;"
 | |
|     else
 | |
|         # user
 | |
|         [ -n "$tb" ] || setx tb=get_oracle_usertb "$dbname"
 | |
|         oracle_user_ve "\
 | |
| update $tb set tem_done = 1, date_done = sysdate where name = '$name';
 | |
| commit;"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function oracle_ensure_opdir() {
 | |
|     if [ -z "$OPDIR" ]; then
 | |
|         ac_set_tmpdir OPDIR
 | |
|         >"$SQLMIGLOG"
 | |
|     fi
 | |
| }
 | |
| function oracle_get_defaults() {
 | |
|     local dir="$1"
 | |
|     if [ -n "$profile" ]; then
 | |
|         if [ "$dbmode" == devel ]; then
 | |
|             if [ -f "$dir/${profile}-ora.conf" ]; then
 | |
|                 echo "$dir/${profile}-ora.conf"; return
 | |
|             elif [ -f "$PROFILEDIR/${profile}-ora.conf" ]; then
 | |
|                 echo "$PROFILEDIR/${profile}-ora.conf"; return
 | |
|             fi
 | |
|         else
 | |
|             if [ -f "$PROFILEDIR/${profile}-ora.conf" ]; then
 | |
|                 echo "$PROFILEDIR/${profile}-ora.conf"; return
 | |
|             elif [ -f "$dir/${profile}-ora.conf" ]; then
 | |
|                 echo "$dir/${profile}-ora.conf"; return
 | |
|             fi
 | |
|         fi
 | |
|     fi
 | |
|     echo "$dir/ora.conf"
 | |
| }
 | |
| function oracle_source_adminconf() {
 | |
|     local dir="$1"
 | |
|     unset ORACLE_SID NLS_LANG ADMINCONNECT USERCONNECT SQLMIGLOG
 | |
|     setx defaults=oracle_get_defaults "$dir"
 | |
|     [ -f "$defaults" ] && source "$defaults"
 | |
|     [ -n "$admindefaults" ] && {
 | |
|         source "$admindefaults" || die
 | |
|     }
 | |
|     [ -n "$oracle_sid" ] && ORACLE_SID="$oracle_sid"
 | |
|     [ -n "$nls_lang" ] && NLS_LANG="$nls_lang"
 | |
|     export ORACLE_SID NLS_LANG
 | |
|     if [ -n "$ADMINCONNECT" ]; then
 | |
|         ADMINDBA=
 | |
|     else
 | |
|         ADMINCONNECT=/
 | |
|         ADMINDBA=1
 | |
|     fi
 | |
|     [ -n "$SQLMIGLOG" ] || SQLMIGLOG="/tmp/sqlmig-${ORACLE_SID}-${dbname}.log"
 | |
| }
 | |
| function oracle_source_userconf() {
 | |
|     local dir="$1" dbname="$2"
 | |
|     unset ORACLE_SID NLS_LANG ADMINCONNECT USERCONNECT SQLMIGLOG SUFFIX CSV2SQL CSV_NULL
 | |
|     setx defaults=oracle_get_defaults "$dir"
 | |
|     [ -f "$defaults" ] && source "$defaults"
 | |
|     [ -f "$dir/ora-${dbname}.conf" ] && source "$dir/ora-${dbname}.conf"
 | |
|     [ -n "$userdefaults" ] && {
 | |
|         source "$userdefaults" || die
 | |
|     }
 | |
|     [ -n "$oracle_sid" ] && ORACLE_SID="$oracle_sid"
 | |
|     [ -n "$nls_lang" ] && NLS_LANG="$nls_lang"
 | |
|     export ORACLE_SID NLS_LANG
 | |
|     if [ -n "$ADMINCONNECT" ]; then
 | |
|         ADMINDBA=
 | |
|     else
 | |
|         ADMINCONNECT=/
 | |
|         ADMINDBA=1
 | |
|     fi
 | |
|     if [ -n "$USERCONNECT" ]; then
 | |
|         USERDBA=
 | |
|     else
 | |
|         USERCONNECT=/
 | |
|         USERDBA=1
 | |
|     fi
 | |
|     [ -n "$SQLMIGLOG" ] || SQLMIGLOG="/tmp/sqlmig-${ORACLE_SID}-${dbname}.log"
 | |
|     [ -z "$suffix" ] && suffix="$SUFFIX"
 | |
|     [ -z "$csv2sql" ] && csv2sql="$CSV2SQL"
 | |
|     [ -z "$csv_null" ] && csv_null="$CSV_NULL"
 | |
|     fix_csv2sql
 | |
|     fix_csv_null
 | |
| }
 | |
| ORACLE_ADMIN_CONF_DONE=
 | |
| function oracle_admin_update() {
 | |
|     local name="$1" update="$2" updateone="$3" done
 | |
|     if [ -z "$updateone" ]; then
 | |
|         if [ -z "$ORACLE_ADMIN_CONF_DONE" ]; then
 | |
|             ORACLE_ADMIN_CONF_DONE=
 | |
|             oracle_tbconf
 | |
|         fi
 | |
|         setx done=oracle_get_done "$name" || die
 | |
|         [ -n "$done" ] && return
 | |
|     fi
 | |
| 
 | |
|     estep "$name"
 | |
|     [ -n "$fake" ] && return
 | |
| 
 | |
|     if [ -z "$updateone" ]; then
 | |
|         oracle_before_update || die
 | |
|     fi
 | |
|     cat "$update" | oracle_admin_ve || abort_on_error
 | |
|     if [ -z "$updateone" ]; then
 | |
|         oracle_after_update || die
 | |
|     fi
 | |
| }
 | |
| function oracle_user_update() {
 | |
|     local name="$1" update="$2" dbname="$3" updateone="$4" done
 | |
|     if [ -z "$updateone" ]; then
 | |
|         setx done=oracle_get_done "$name" "$dbname" || die
 | |
|         [ -n "$done" ] && return
 | |
|     fi
 | |
| 
 | |
|     estep "$name"
 | |
|     [ -n "$fake" ] && return
 | |
| 
 | |
|     if [ -z "$updateone" ]; then
 | |
|         oracle_before_update "$dbname" || die
 | |
|     fi
 | |
|     cat "$update" | oracle_user_ve || abort_on_error
 | |
|     if [ -z "$updateone" ]; then
 | |
|         oracle_after_update "$dbname" || die
 | |
|     fi
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| 
 | |
| MODE=auto
 | |
| PROFILEDIR=/etc/sqlmig
 | |
| prod_PROFILE_MODE=prod
 | |
| test_PROFILE_MODE=devel
 | |
| set_defaults sqlmig
 | |
| 
 | |
| admindefaults=
 | |
| userdefaults=
 | |
| user=
 | |
| password=
 | |
| pwset=
 | |
| host=
 | |
| port=
 | |
| socket=
 | |
| charset=
 | |
| oracle_sid=
 | |
| nls_lang=
 | |
| suffix=
 | |
| csv2sql=
 | |
| csv_null=
 | |
| load_data=
 | |
| profile=
 | |
| type=auto
 | |
| action=update
 | |
| updatedir=
 | |
| exportdir=
 | |
| dbdir=
 | |
| dbname=
 | |
| updateone=
 | |
| force=
 | |
| data_csv=auto
 | |
| mode="$MODE"
 | |
| drop=
 | |
| drop_only=
 | |
| create_only=
 | |
| args=(
 | |
|     --help '$exit_with display_help'
 | |
|     -g:,--admin-defaults-file: admindefaults=
 | |
|     -C:,--defaults-file: userdefaults=
 | |
|     -u:,--user: user=
 | |
|     -p:,--password: '$set@ password; pwset=1'
 | |
|     -h:,--host: host=
 | |
|     --port: port=
 | |
|     --socket: socket=
 | |
|     --character-set: charset=
 | |
|     -s:,--oracle-sid: oracle_sid=
 | |
|     --nls-lang: nls_lang=
 | |
|     --suffix: suffix=
 | |
|     --csv2sql csv2sql=1
 | |
|     --csv-null: csv_null=
 | |
|     --csv-null-empty csv_null=empty
 | |
|     --csv-null-mysql csv_null='\N'
 | |
|     --csv-null-upper csv_null=NULL
 | |
|     --no-csv2sql csv2sql=0
 | |
|     --load-data: load_data=
 | |
|     --profile: profile=
 | |
|     -P,--prod profile=prod
 | |
|     -T,--test profile=test
 | |
|     --mysql type=mysql
 | |
|     --oracle type=oracle
 | |
|     -0,--init action=init
 | |
|     -e:,--export: '$action=export; set@ exportdir'
 | |
|     -c,--connect action=connect
 | |
|     -r,--restore-test action=restore_test
 | |
|     --update-all action=update
 | |
|     -t:,--updatedir: updatedir=
 | |
|     -d:,--databasedir: dbdir=
 | |
|     -b:,--database: dbname=
 | |
|     -f,--update-one updateone=1
 | |
|     -n,--fake fake=1
 | |
|     --force,--continue-on-error force=1
 | |
|     --no-data-csv data_csv=
 | |
|     --force-data-csv data_csv=force
 | |
|     --prod-mode-dangerous mode=prod
 | |
|     --devel-mode mode=devel
 | |
|     -Z,--recreate drop=1
 | |
|     --drop-only '$drop=1; drop_only=1'
 | |
|     --create-only create_only=1
 | |
| )
 | |
| parse_args "$@"; set -- "${args[@]}"
 | |
| 
 | |
| setx cwd=pwd
 | |
| if [ -z "$dbdir" -a -z "$updatedir" ]; then
 | |
|     setx parentdir=dirname -- "$cwd"
 | |
|     if __check_devel_dir src/main/resources/database; then
 | |
|         enote "Autosélection src/main/resources/database/"
 | |
|     elif __check_devel_dir config/sqlmig; then
 | |
|         enote "Autosélection config/sqlmig/"
 | |
|     elif __check_devel_dir support/database; then
 | |
|         enote "Autosélection support/database/"
 | |
|     elif __check_devel_dir database; then
 | |
|         enote "Autosélection database/"
 | |
|     elif __check_mysql_prod_dir; then
 | |
|         [ "$type" == auto ] && type=mysql
 | |
|     fi
 | |
| fi
 | |
| 
 | |
| [ -n "$updatedir" ] && setx updatedir=abspath "$updatedir"
 | |
| [ -n "$dbdir" ] && setx dbdir=abspath "$dbdir"
 | |
| 
 | |
| ################################################################################
 | |
| if [ "$action" == init ]; then
 | |
|     [ -n "$dbdir" -a -z "$dbname" ] && setx dbname=basename "$dbdir"
 | |
|     [ -n "$dbname" ] || dbname="$1"
 | |
|     read_value ${dbname:+-i} "Entrez le nom de la base de données" dbname "$dbname"
 | |
| 
 | |
|     if [ -z "$dbdir" -a -n "$updatedir" ]; then
 | |
|         dbdir="$updatedir/$dbname"
 | |
|     elif [ -z "$dbdir" ]; then
 | |
|         dbdir="$dbname"
 | |
|     fi
 | |
|     read_value ${dbdir:+-i} "Entrez le répertoire dans lequel créer les définitions" dbdir "$dbdir"
 | |
|     setx dbdir=abspath "$dbdir"
 | |
| 
 | |
|     ask_yesno "Voulez-vous créer les fichiers initiaux pour la base de données $dbname dans le répertoire $(ppath "$dbdir")?" O || die
 | |
| 
 | |
|     estep "Création du répertoire $dbdir"
 | |
|     [ -d "$dbdir" ] || mkdir -p "$dbdir" || die
 | |
| 
 | |
|     [ "$type" == auto ] && type=mysql
 | |
| 
 | |
|     if [ "$type" == mysql ]; then
 | |
|         if [ ! -f "$dbdir/00dropdb.sql" ]; then
 | |
|             estep "00dropdb.sql"
 | |
|             echo >"$dbdir/00dropdb.sql" "\
 | |
| -- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| -- @sqlmig drop
 | |
| 
 | |
| drop database if exists @@database@@;"
 | |
|         fi
 | |
| 
 | |
|         if [ ! -f "$dbdir/01createdb.sql" ]; then
 | |
|             estep "01createdb.sql"
 | |
|             echo >"$dbdir/01createdb.sql" "\
 | |
| -- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| -- @sqlmig create
 | |
| 
 | |
| create database @@database@@;"
 | |
|         fi
 | |
| 
 | |
|         if [ ! -f "$dbdir/02grants.sql" ]; then
 | |
|             estep "02grants.sql"
 | |
|             echo >"$dbdir/02grants.sql" "\
 | |
| -- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| -- @sqlmig admin
 | |
| 
 | |
| create user '$dbname' identified by '$dbname';
 | |
| grant all privileges on $dbname.* to '$dbname';"
 | |
|         fi
 | |
| 
 | |
|         if [ ! -f "$dbdir/my.cnf" ]; then
 | |
|             estep "my.cnf"
 | |
|             echo >"$dbdir/my.cnf" "\
 | |
| # Paramètres de connexion par défaut
 | |
| [client]
 | |
| #user=
 | |
| #password=
 | |
| #host=localhost
 | |
| #port=3306
 | |
| #socket=/var/run/mysqld/mysqld.sock
 | |
| 
 | |
| [mysql]
 | |
| default-character-set=utf8
 | |
| 
 | |
| [sqlmig]
 | |
| #suffix="
 | |
|         fi
 | |
| 
 | |
|         if [ ! -f "$dbdir/my-${dbname}.cnf" ]; then
 | |
|             estep "my-${dbname}.cnf"
 | |
|             echo >"$dbdir/my-${dbname}.cnf" "\
 | |
| # Paramètres de connexion pour $dbname
 | |
| [client]
 | |
| #user=
 | |
| #password=
 | |
| 
 | |
| [sqlmig]
 | |
| #csv2sql=0
 | |
| csv_null=
 | |
| #load-data=default"
 | |
|        fi
 | |
| 
 | |
|     elif [ "$type" == oracle ]; then
 | |
|         if [ ! -f "$dbdir/00dropuser.sql" ]; then
 | |
|             estep "00dropuser.sql"
 | |
|             echo >"$dbdir/00dropuser.sql" "\
 | |
| -- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| -- @sqlmig drop
 | |
| 
 | |
| drop user $dbname cascade;"
 | |
|         fi
 | |
| 
 | |
|         if [ ! -f "$dbdir/01createuser.sql" ]; then
 | |
|             estep "01createuser.sql"
 | |
|             echo >"$dbdir/01createuser.sql" "\
 | |
| -- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| -- @sqlmig create
 | |
| 
 | |
| create user $dbname identified by \"$dbname\";
 | |
| grant connect to $dbname;
 | |
| grant resource to $dbname;"
 | |
|         fi
 | |
| 
 | |
|         if [ ! -f "$dbdir/ora.conf" ]; then
 | |
|             estep "ora.conf"
 | |
|             echo >"$dbdir/ora.conf" "\
 | |
| # Paramètres de connexion par défaut
 | |
| ORACLE_SID=orcl
 | |
| NLS_LANG=FRENCH_FRANCE.AL32UTF8
 | |
| #NLS_LANG=AMERICAN_AMERICA.AL32UTF8
 | |
| # paramètres de connexion pour les mises à jour administratives
 | |
| # si aucune valeur n'est spécifiée, la valeur effective est '/ as sysdba' mais
 | |
| # cela requière que la mise à jour soit faite avec une connexion locale.
 | |
| ADMINCONNECT=
 | |
| # paramètres de connexion pour les mises à jour utilisateur
 | |
| USERCONNECT=$dbname/password
 | |
| # logs des mises à jour
 | |
| SQLMIGLOG=\"/tmp/sqlmig-\${ORACLE_SID}-${dbname}.log\"
 | |
| # divers
 | |
| #SUFFIX=
 | |
| #CSV2SQL=0
 | |
| CSV_NULL="
 | |
|         fi
 | |
| 
 | |
|     else
 | |
|         die "BUG: $type: type non implémenté"
 | |
|     fi
 | |
| 
 | |
|     exit 0
 | |
| 
 | |
| ################################################################################
 | |
| elif [ "$action" == export ]; then
 | |
|     [ -n "$exportdir" ] || setx exportdir=find_mysqldupdatedir
 | |
|     check_mysqldupdatedir "$exportdir"
 | |
|     setx exportdir=abspath "$exportdir/updates"
 | |
| 
 | |
|     if [ -n "$dbdir" ]; then
 | |
|         dbdirs=("$dbdir")
 | |
|     elif [ -z "$updatedir" ]; then
 | |
|         array_lsfiles files . "*.sql" "*my.cnf" "my-*.cnf" "*ora.conf" "ora-*.conf"
 | |
|         if [ ${#files[*]} -gt 0 ]; then
 | |
|             enote "Autosélection répertoire courant"
 | |
|             dbdir="$cwd"
 | |
|             dbdirs=("$dbdir")
 | |
|         else
 | |
|             die "Vous devez spécifier l'option -b"
 | |
|         fi
 | |
|     elif [ -n "$dbname" ]; then
 | |
|         dbdirs=("$updatedir/$dbname")
 | |
|     else
 | |
|         array_lsdirs dbdirs "$updatedir"
 | |
|     fi
 | |
| 
 | |
|     for dbdir in "${dbdirs[@]}"; do
 | |
|         setx dbname=basename -- "$dbdir"
 | |
|         # TEMPLATE.d est spécial dans mysqld-update: il faut l'ignorer
 | |
|         [ "$dbname" != TEMPLATE.d ] || continue
 | |
| 
 | |
|         etitled "$dbname"
 | |
|         destdir="$exportdir/$dbname"
 | |
|         array_lsfiles updates "$dbdir"
 | |
|         for update in "${updates[@]}"; do
 | |
|             [ -d "$destdir" ] || mkdir -p "$destdir"
 | |
|             [[ "$update" == "*.devel.sql" ]] && continue
 | |
|             copy_update "$update" "$destdir"
 | |
|         done
 | |
|         eend; eclearp
 | |
|     done
 | |
| 
 | |
|     exit 0
 | |
| 
 | |
| ################################################################################
 | |
| elif [ "$action" == connect ]; then
 | |
|     set_dbdirs
 | |
| 
 | |
|     force_dbname="$dbname"
 | |
|     force_suffix="$suffix"
 | |
|     for dbdir in "${dbdirs[@]}"; do
 | |
|         dbname="$force_dbname"
 | |
|         [ -n "$dbname" ] || setx dbname=basename "$dbdir"
 | |
|         suffix="$force_suffix"
 | |
|         etitle "$dbname"
 | |
| 
 | |
|         ensure_dbtype "$dbdir" "$type"
 | |
|         ensure_dbmode "$dbtype" "$mode"
 | |
| 
 | |
|         if [ "$dbtype" == mysql ]; then
 | |
|             # construire les paramètres pour mysql
 | |
|             mysql_set_userargs "$dbdir" "$dbname"
 | |
|             mysql_set_mysqlargs
 | |
| 
 | |
|             if [ -n "$suffix" ]; then
 | |
|                 estepi "Suffixe: $dbname --> $dbname$suffix"
 | |
|                 dbname="$dbname$suffix"
 | |
|             fi
 | |
| 
 | |
|             array_del mysqlargs -B # désactiver le mode batch
 | |
|             mysql "${userargs[@]}" "${mysqlargs[@]}" -D "$dbname"
 | |
| 
 | |
|         elif [ "$dbtype" == oracle ]; then
 | |
|             # lire les paramètres
 | |
|             oracle_source_userconf "$dbdir" "$dbname"
 | |
|             oracle_ensure_opdir
 | |
| 
 | |
|             if [ -n "$suffix" ]; then
 | |
|                 estepi "Suffixe: $dbname --> $dbname$suffix"
 | |
|                 dbname="$dbname$suffix"
 | |
|             fi
 | |
| 
 | |
|             sqlplus "$USERCONNECT@$ORACLE_SID" ${USERDBA:+as sysdba} "$@"
 | |
| 
 | |
|         else
 | |
|             die "BUG: $dbtype: type non implémenté"
 | |
|         fi
 | |
| 
 | |
|         eend
 | |
|     done
 | |
|     exit 0
 | |
| 
 | |
| ################################################################################
 | |
| elif [ "$action" == restore_test ]; then
 | |
|     set_dbdirs
 | |
| 
 | |
|     if [ ${#dbdirs[*]} -gt 1 ]; then
 | |
|         die "Avec --restore-test, une seule base de données doit être spécifiée"
 | |
|     fi
 | |
| 
 | |
|     dbdir="${dbdirs[0]}"
 | |
|     [ -n "$dbname" ] || setx dbname=basename "$dbdir"
 | |
| 
 | |
|     etitle "$dbname"
 | |
| 
 | |
|     ensure_dbtype "$dbdir" "$type"
 | |
|     ensure_dbmode "$dbtype" "$mode"
 | |
| 
 | |
|     [ "$dbtype" == mysql ] || die "Seule les bases de type MySQL sont supportées"
 | |
| 
 | |
|     # construire les paramètres pour mysql
 | |
|     mysql_set_userargs "$dbdir" "$dbname"
 | |
|     mysql_set_mysqlargs
 | |
| 
 | |
|     if [ -n "$suffix" ]; then
 | |
|         estepi "Suffixe: $dbname --> $dbname$suffix"
 | |
|         dbname="$dbname$suffix"
 | |
|     fi
 | |
| 
 | |
|     dump="$1"
 | |
|     [ -n "$dump" ] || die "Vous devez spécifier le fichier de dump"
 | |
|     [ -f "$dump" ] || die "$dump: fichier de dump introuvable"
 | |
| 
 | |
|     ac_set_tmpdir tmpdir
 | |
|     if [[ "$dump" == *.gz ]]; then
 | |
|         gzip -dc "$dump" >"$tmpdir/prod.sql"
 | |
|     elif [[ "$dump" == *.sql ]]; then
 | |
|         cat "$dump" >"$tmpdir/prod.sql"
 | |
|     else
 | |
|         die "$dump: n'est pas un fichier sql"
 | |
|     fi
 | |
|     dump="$tmpdir/prod.sql"
 | |
| 
 | |
|     pname="$dbname"
 | |
|     tname="${dbname}_test"
 | |
|     sed <"$tmpdir/prod.sql" >"$tmpdir/test.sql" "\
 | |
| s/\`$pname\`/\`$tname\`/g
 | |
| s/\`${pname}_updates_\`/\`${tname}_updates_\`/g"
 | |
| 
 | |
|     enote "Vous allez restaurer un fichier de sauvegarde de le base $pname vers la base $tname"
 | |
|     ask_yesno "Voulez-vous continuer?" X || die
 | |
| 
 | |
|     array_del mysqlargs -B # désactiver le mode batch
 | |
|     mysql "${userargs[@]}" "${mysqlargs[@]}" <"$tmpdir/test.sql"
 | |
|     ac_clean "$tmpdir"
 | |
| 
 | |
|     exit 0
 | |
| 
 | |
| ################################################################################
 | |
| elif [ "$action" != update ]; then
 | |
|     die "BUG: $action: action non implémentée"
 | |
| fi
 | |
| 
 | |
| ################################################################################
 | |
| # update
 | |
| 
 | |
| set_dbdirs
 | |
| if [ -n "$updateone" ]; then
 | |
|     updatefiles=()
 | |
|     for updatefile in "$@"; do
 | |
|         array_add updatefiles "$(abspath "$updatefile")"
 | |
|     done
 | |
| fi
 | |
| function should_update() {
 | |
|     local update="$1" name
 | |
|     setx name=basename "$update"
 | |
|     if [ -n "$updateone" ]; then
 | |
|         # prendre tous les fichiers sélectionnés par -f
 | |
|         array_contains updatefiles "$update"
 | |
|         return $?
 | |
|     elif [ "${name#maint-}" != "$name" ]; then
 | |
|         # ignorer les opérations de maintenance par défaut
 | |
|         return 1
 | |
|     elif [ "$dbmode" != devel -a "${name%.devel.*}" != "$name" ]; then
 | |
|         # si on est en mode autre que devel, le nom ne doit pas se terminer
 | |
|         # par .devel.*
 | |
|         return 1
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| # répertoire temporaire pour Oracle
 | |
| OPDIR=
 | |
| 
 | |
| if [ -n "$updatedir" ]; then
 | |
|     ## mises à jour administratives
 | |
|     array_lsfiles updates "$updatedir" "*.sql"
 | |
|     if [ ${#updates[*]} -gt 0 ]; then
 | |
|         ensure_dbtype "$updatedir" "$type"
 | |
|         ensure_dbmode "$dbtype" "$mode"
 | |
|         if [ "$dbtype" == mysql ]; then
 | |
|             # construire les paramètres pour mysql
 | |
|             mysql_set_adminargs "$updatedir"
 | |
|             mysql_set_mysqlargs
 | |
| 
 | |
|             # Mises à jour
 | |
|             etitled "Mises à jour admin"
 | |
|             for update in "${updates[@]}"; do
 | |
|                 should_update "$update" || continue
 | |
|                 mysql_admin_update "${update#$updatedir/}" "$update" "$updateone"
 | |
|             done
 | |
|             eend; eclearp
 | |
| 
 | |
|         elif [ "$dbtype" == oracle ]; then
 | |
|             # lire les paramètres
 | |
|             oracle_source_adminconf "$updatedir"
 | |
|             oracle_ensure_opdir
 | |
| 
 | |
|             # Mises à jour
 | |
|             etitled "Mises à jour"
 | |
|             for update in "${updates[@]}"; do
 | |
|                 should_update "$update" || continue
 | |
|                 oracle_admin_update "${update#$updatedir/}" "$update" "$updateone"
 | |
|             done
 | |
|             eend; eclearp
 | |
|         fi
 | |
|     fi
 | |
| fi
 | |
| 
 | |
| ## mises à jour utilisateur
 | |
| force_dbname="$dbname"
 | |
| force_suffix="$suffix"
 | |
| for dbdir in "${dbdirs[@]}"; do
 | |
|     dbname="$force_dbname"
 | |
|     [ -n "$dbname" ] || setx dbname=basename "$dbdir"
 | |
|     suffix="$force_suffix"
 | |
|     etitle "$dbname"
 | |
| 
 | |
|     ensure_dbtype "$dbdir" "$type"
 | |
|     ensure_dbmode "$dbtype" "$mode"
 | |
| 
 | |
|     ############################################################################
 | |
|     if [ "$dbtype" == mysql ]; then
 | |
|         # construire les paramètres pour mysql
 | |
|         mysql_set_adminargs "$dbdir"
 | |
|         mysql_set_userargs "$dbdir" "$dbname"
 | |
|         mysql_set_mysqlargs
 | |
| 
 | |
|         if is_yes "$csv2sql" && [ -n "$data_csv" ]; then
 | |
|             # Conversion csv --> sql
 | |
|             array_lsfiles csvs "$dbdir" "*.csv"
 | |
| 
 | |
|             etitled "Conversion"
 | |
|             for csv in "${csvs[@]}"; do
 | |
|                 setx csvname=basename -- "$csv"
 | |
|                 sql="${csv%.csv}.sql"
 | |
|                 if [ "$data_csv" != force ]; then
 | |
|                     testnewer "$csv" "$sql" || continue
 | |
|                 fi
 | |
| 
 | |
|                 estep "$csvname --> ${csvname%.csv}.sql"
 | |
|                 eval "$(get_csvinfo "$csvname")"
 | |
|                 mysqlloadcsv_args=(
 | |
|                     ${truncate:+-T}
 | |
|                     -Z "$csv_null"
 | |
|                     --prefix "-- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8"
 | |
|                     -nIf "$csv" "$table"
 | |
|                 )
 | |
|                 "$scriptdir/mysqlloadcsv" "${mysqlloadcsv_args[@]}" >"$sql"
 | |
|             done
 | |
|             eend; eclearp
 | |
|         fi
 | |
| 
 | |
|         # lister les mises à jour disponibles
 | |
|         drops=()
 | |
|         creates=()
 | |
|         updates=()
 | |
|         have_csv=
 | |
|         array_lsfiles files "$dbdir" "*.sql" "*.csv"
 | |
|         for file in "${files[@]}"; do
 | |
|             if [[ "$file" == *.sql ]]; then
 | |
|                 if have_tag drop "$file"; then
 | |
|                     array_add drops "$file"
 | |
|                 elif have_tag create "$file"; then
 | |
|                     array_add creates "$file"
 | |
|                 else
 | |
|                     array_add updates "$file"
 | |
|                 fi
 | |
|             elif [ ! -f "${file%.csv}.sql" ]; then
 | |
|                 # n'ajouter le CSV que si le fichier SQL correspondant n'existe pas
 | |
|                 array_add updates "$file"
 | |
|                 have_csv=1
 | |
|             fi
 | |
|         done
 | |
| 
 | |
|         if [ -n "$suffix" ]; then
 | |
|             estepi "Suffixe: $dbname --> $dbname$suffix"
 | |
|             dbname="$dbname$suffix"
 | |
|         fi
 | |
|         if is_no "$csv2sql" && [ -n "$have_csv" ]; then
 | |
|             estepi "Chargement des fichiers CSV avec la méthode $load_data"
 | |
|         fi
 | |
| 
 | |
|         # Suppression
 | |
|         if [ -n "$drop" ]; then
 | |
|             [ "$dbmode" == devel ] || die "La suppression de base de données n'est pas autorisée en mode production"
 | |
|             etitle "Suppression"
 | |
|             if ! ask_yesno "Etes-vous sûr de vouloir supprimer la base de données $dbname?" X; then
 | |
|                 ewarn "Suppression annulée, les autres opérations ne seront pas effectuées"
 | |
|                 eend; continue
 | |
|             fi
 | |
|             for drop in "${drops[@]}"; do
 | |
|                 should_update "$update" || continue
 | |
|                 setx name=basename "$drop"
 | |
|                 estep "$name"
 | |
|                 [ -n "$fake" ] && continue
 | |
| 
 | |
|                 sed "s/@@database@@/$dbname/g" "$drop" | mysql_admin_qe || abort_on_error "drop: $name"
 | |
|             done
 | |
|             eend
 | |
|             [ -n "$drop_only" ] && { eend; continue; }
 | |
|         fi
 | |
| 
 | |
|         # Création
 | |
|         if ! mysql_admin_qe "select 1" "$dbname"; then
 | |
|             etitled "Création"
 | |
|             for create in "${creates[@]}"; do
 | |
|                 should_update "$update" || continue
 | |
|                 setx name=basename "$create"
 | |
|                 estep "$name"
 | |
|                 [ -n "$fake" ] && continue
 | |
| 
 | |
|                 sed "s/@@database@@/$dbname/g" "$create" | mysql_admin_qe || abort_on_error "create: $name"
 | |
|             done
 | |
|             eend; eclearp
 | |
|         fi
 | |
|         [ -n "$create_only" ] && { eend; continue; }
 | |
| 
 | |
|         # Mises à jour
 | |
|         etitled "Mises à jour"
 | |
|         mysql_tbconf "$dbname"
 | |
|         for update in "${updates[@]}"; do
 | |
|             should_update "$update" || continue
 | |
|             if [[ "$update" == *.sql ]]; then
 | |
|                 # fichier SQL
 | |
|                 if have_tag admin "$update"; then
 | |
|                     [ -n "$updatedir" ] && name="${update#$updatedir/}" || name="${update#$dbdir/}"
 | |
|                     mysql_admin_update "$name" "$update" "$updateone"
 | |
|                 else
 | |
|                     mysql_user_update "${update#$dbdir/}" "$update" "$dbname" "$updateone"
 | |
|                 fi
 | |
|             elif is_no "$csv2sql"; then
 | |
|                 # fichier CSV, ne les traiter que si on est en mode --no-csv2sql
 | |
|                 mysql_user_update "${update#$dbdir/}" "$update" "$dbname" "$updateone"
 | |
|             fi
 | |
|         done
 | |
|         eend; eclearp
 | |
| 
 | |
|     ############################################################################
 | |
|     elif [ "$dbtype" == oracle ]; then
 | |
|         [ -n "$OPDIR" ] || ac_set_tmpdir OPDIR
 | |
| 
 | |
|         # lire les paramètres
 | |
|         oracle_source_userconf "$dbdir" "$dbname"
 | |
|         oracle_ensure_opdir
 | |
| 
 | |
|         # lister les mises à jour disponibles
 | |
|         drops=()
 | |
|         creates=()
 | |
|         updates=()
 | |
|         have_csv=
 | |
|         array_lsfiles files "$dbdir" "*.sql" "*.csv"
 | |
|         for file in "${files[@]}"; do
 | |
|             if [[ "$file" == *.sql ]]; then
 | |
|                 if have_tag drop "$file"; then
 | |
|                     array_add drops "$file"
 | |
|                 elif have_tag create "$file"; then
 | |
|                     array_add creates "$file"
 | |
|                 else
 | |
|                     array_add updates "$file"
 | |
|                 fi
 | |
|             elif [ ! -f "${file%.csv}.sql" ]; then
 | |
|                 # n'ajouter le CSV que si le fichier SQL correspondant n'existe pas
 | |
|                 array_add updates "$file"
 | |
|                 have_csv=1
 | |
|             fi
 | |
|         done
 | |
| 
 | |
|         if [ -n "$suffix" ]; then
 | |
|             estepi "Suffixe: $dbname --> $dbname$suffix"
 | |
|             dbname="$dbname$suffix"
 | |
|         fi
 | |
| 
 | |
|         # Suppression
 | |
|         if [ -n "$drop" ]; then
 | |
|             [ "$dbmode" == devel ] || die "La suppression de user n'est pas autorisée en mode production"
 | |
|             etitle "Suppression"
 | |
|             if ! ask_yesno "Etes-vous sûr de vouloir supprimer le user $dbname?" X; then
 | |
|                 ewarn "Suppression annulée, les autres opérations ne seront pas effectuées"
 | |
|                 eend; continue
 | |
|             fi
 | |
|             for drop in "${drops[@]}"; do
 | |
|                 should_update "$update" || continue
 | |
|                 setx name=basename "$drop"
 | |
|                 estep "$name"
 | |
|                 [ -n "$fake" ] && continue
 | |
| 
 | |
|                 sed "s/@@database@@/$dbname/g" "$drop" | oracle_admin_ve || abort_on_error "drop: $name"
 | |
|             done
 | |
|             eend
 | |
|             [ -n "$drop_only" ] && { eend; continue; }
 | |
|         fi
 | |
| 
 | |
|         # Création
 | |
|         if ! oracle_admin_have_user "$dbname"; then
 | |
|             etitled "Création"
 | |
|             for create in "${creates[@]}"; do
 | |
|                 should_update "$update" || continue
 | |
|                 setx name=basename "$create"
 | |
|                 estep "$name"
 | |
|                 [ -n "$fake" ] && continue
 | |
| 
 | |
|                 sed "s/@@database@@/$dbname/g" "$create" | oracle_admin_ve || abort_on_error "create: $name"
 | |
|             done
 | |
|             eend; eclearp
 | |
|         fi
 | |
|         [ -n "$create_only" ] && { eend; continue; }
 | |
| 
 | |
|         # Mises à jour
 | |
|         etitled "Mises à jour"
 | |
|         oracle_tbconf "$dbname"
 | |
|         for update in "${updates[@]}"; do
 | |
|             should_update "$update" || continue
 | |
|             if [[ "$update" == *.sql ]]; then
 | |
|                 # fichier SQL
 | |
|                 if have_tag admin "$update"; then
 | |
|                     [ -n "$updatedir" ] && name="${update#$updatedir/}" || name="${update#$dbdir/}"
 | |
|                     oracle_admin_update "$name" "$update" "$updateone"
 | |
|                 else
 | |
|                     oracle_user_update "${update#$dbdir/}" "$update" "$dbname" "$updateone"
 | |
|                 fi
 | |
|             fi
 | |
|         done
 | |
|         eend; eclearp
 | |
| 
 | |
|     ############################################################################
 | |
|     else
 | |
|         die "BUG: $dbtype: type non implémenté"
 | |
|     fi
 | |
| 
 | |
|     eend
 | |
| done
 |