1402 lines
47 KiB
Bash
Executable File
1402 lines
47 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.
|
|
|
|
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
|
|
|
|
--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.
|
|
--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 UPDATE
|
|
Forcer l'application de la mise à jour spécifiée. Ne pas mettre à jour
|
|
l'état des mises à jour installées. Avec cette option, tout se passe
|
|
comme si le seul fichier existant est celui spécifié.
|
|
|
|
-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 convertir les fichiers *-data.csv en fichier .sql
|
|
correspondant. Cette conversion n'est supportée que pour MySQL pour le
|
|
moment, et un fichier de la forme NUMTABLE-data.csv où NUM est une valeur
|
|
numérique est transformé en une suite d'insertions dans la table TABLE.
|
|
La variante NUMTABLE-data_truncate.csv ajoute les données dans la table
|
|
après l'avoir vidée avec truncate.
|
|
--force-data-csv
|
|
Forcer la conversion des fichiers *-data.csv. 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
|
|
}
|
|
|
|
################################################################################
|
|
# 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_set_userargs() {
|
|
local dir="$1" dbname="$2" defaults set_suffix tmpsuffix
|
|
userargs=()
|
|
setx defaults=mysql_get_defaults "$dir"
|
|
[ -z "$suffix" ] && set_suffix=1
|
|
if [ -f "$defaults" ]; then
|
|
array_add userargs --defaults-file="$defaults"
|
|
if [ -n "$set_suffix" ]; then
|
|
setx tmpsuffix=mconf_get "$defaults" sqlmig suffix
|
|
[ -n "$tmpsuffix" ] && suffix="$tmpsuffix"
|
|
fi
|
|
if [ -n "$userdefaults" ]; then
|
|
array_add userargs --defaults-extra-file="$userdefaults"
|
|
if [ -n "$set_suffix" ]; then
|
|
setx tmpsuffix=mconf_get "$userdefaults" sqlmig suffix
|
|
[ -n "$tmpsuffix" ] && suffix="$tmpsuffix"
|
|
fi
|
|
elif [ -f "$dir/my-${dbname}.cnf" ]; then
|
|
array_add userargs --defaults-extra-file="$dir/my-${dbname}.cnf"
|
|
if [ -n "$set_suffix" ]; then
|
|
setx tmpsuffix=mconf_get "$dir/my-${dbname}.cnf" sqlmig suffix
|
|
[ -n "$tmpsuffix" ] && suffix="$tmpsuffix"
|
|
fi
|
|
fi
|
|
elif [ -n "$userdefaults" ]; then
|
|
array_add userargs --defaults-file="$userdefaults"
|
|
if [ -n "$set_suffix" ]; then
|
|
setx tmpsuffix=mconf_get "$userdefaults" sqlmig suffix
|
|
[ -n "$tmpsuffix" ] && suffix="$tmpsuffix"
|
|
fi
|
|
elif [ -f "$dir/my-${dbname}.cnf" ]; then
|
|
array_add userargs --defaults-file="$dir/my-${dbname}.cnf"
|
|
if [ -n "$set_suffix" ]; then
|
|
setx tmpsuffix=mconf_get "$dir/my-${dbname}.cnf" sqlmig suffix
|
|
[ -n "$tmpsuffix" ] && suffix="$tmpsuffix"
|
|
fi
|
|
fi
|
|
[ ${#userargs[*]} -gt 0 ] || array_add userargs --default-character-set utf8
|
|
}
|
|
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" updatefile="$3" done
|
|
if [ -z "$updatefile" ]; 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 "$updatefile" ]; then
|
|
mysql_before_update || die
|
|
fi
|
|
cat "$update" | mysql_admin_ve || abort_on_error
|
|
if [ -z "$updatefile" ]; then
|
|
mysql_after_update || die
|
|
fi
|
|
}
|
|
function mysql_user_update() {
|
|
local name="$1" update="$2" dbname="$3" updatefile="$4" done
|
|
if [ -z "$updatefile" ]; 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 "$updatefile" ]; then
|
|
mysql_before_update "$dbname" || die
|
|
fi
|
|
cat "$update" | mysql_user_ve || abort_on_error
|
|
if [ -z "$updatefile" ]; 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
|
|
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"
|
|
}
|
|
ORACLE_ADMIN_CONF_DONE=
|
|
function oracle_admin_update() {
|
|
local name="$1" update="$2" updatefile="$3" done
|
|
if [ -z "$updatefile" ]; 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 "$updatefile" ]; then
|
|
oracle_before_update || die
|
|
fi
|
|
cat "$update" | oracle_admin_ve || abort_on_error
|
|
if [ -z "$updatefile" ]; then
|
|
oracle_after_update || die
|
|
fi
|
|
}
|
|
function oracle_user_update() {
|
|
local name="$1" update="$2" dbname="$3" updatefile="$4" done
|
|
if [ -z "$updatefile" ]; then
|
|
setx done=oracle_get_done "$name" "$dbname" || die
|
|
[ -n "$done" ] && return
|
|
fi
|
|
|
|
estep "$name"
|
|
[ -n "$fake" ] && return
|
|
|
|
if [ -z "$updatefile" ]; then
|
|
oracle_before_update "$dbname" || die
|
|
fi
|
|
cat "$update" | oracle_user_ve || abort_on_error
|
|
if [ -z "$updatefile" ]; 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=
|
|
profile=
|
|
type=auto
|
|
action=update
|
|
updatedir=
|
|
exportdir=
|
|
dbdir=
|
|
dbname=
|
|
updatefile=
|
|
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=
|
|
--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
|
|
--update-all action=update
|
|
-t:,--updatedir: updatedir=
|
|
-d:,--databasedir: dbdir=
|
|
-b:,--database: dbname=
|
|
-f:,--update-one: updatefile=
|
|
-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 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/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"
|
|
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="
|
|
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 \"password\";
|
|
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=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\""
|
|
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" != update ]; then
|
|
die "BUG: $action: action non implémentée"
|
|
fi
|
|
|
|
################################################################################
|
|
# update
|
|
|
|
set_dbdirs
|
|
[ -n "$updatefile" ] && setx updatefile=abspath "$updatefile"
|
|
|
|
# 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
|
|
setx name=basename "$update"
|
|
[ "$dbmode" == devel -o "${name%.devel.sql}" == "$name" ] || continue
|
|
[ -z "$updatefile" -o "$updatefile" == "$update" ] || continue
|
|
name="${update#$updatedir/}"
|
|
mysql_admin_update "$name" "$update" "$updatefile"
|
|
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
|
|
setx name=basename "$update"
|
|
[ "$dbmode" == devel -o "${name%.devel.sql}" == "$name" ] || continue
|
|
[ -z "$updatefile" -o "$updatefile" == "$update" ] || continue
|
|
name="${update#$updatedir/}"
|
|
oracle_admin_update "$name" "$update" "$updatefile"
|
|
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"
|
|
|
|
# Conversion csv --> sql
|
|
array_lsfiles csvs "$dbdir" "*.csv"
|
|
if [ "$dbtype" == mysql -a -n "$data_csv" ]; then
|
|
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 "$(awk '{
|
|
truncate = ($0 ~ /-data_truncate(.devel)?.csv$/)? "1": ""
|
|
sub(/^.*\//, "")
|
|
sub(/^[0-9]+/, "")
|
|
sub(/\.csv$/, "")
|
|
sub(/\.devel$/, "")
|
|
sub(/-data(_[a-z]+*)?$/, "")
|
|
print "truncate=" truncate
|
|
gsub(/'\''/, "'\'\\\\\'\''")
|
|
print "table='\''" $0 "'\''"
|
|
}' <<<"$csvname")" #"
|
|
"$scriptdir/mysqlloadcsv" >"$sql" ${truncate:+-T} -nIf "$csv" "$table" --prefix "-- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8"
|
|
done
|
|
eend; eclearp
|
|
fi
|
|
|
|
# lister les mises à jour disponibles
|
|
drops=()
|
|
creates=()
|
|
updates=()
|
|
array_lsfiles files "$dbdir" "*.sql"
|
|
for file in "${files[@]}"; do
|
|
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
|
|
done
|
|
|
|
############################################################################
|
|
if [ "$dbtype" == mysql ]; then
|
|
# construire les paramètres pour mysql
|
|
mysql_set_adminargs "$dbdir"
|
|
mysql_set_userargs "$dbdir" "$dbname"
|
|
mysql_set_mysqlargs
|
|
|
|
if [ -n "$suffix" ]; then
|
|
estepi "Suffixe: $dbname --> $dbname$suffix"
|
|
dbname="$dbname$suffix"
|
|
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
|
|
setx name=basename "$drop"
|
|
[ "$dbmode" == devel -o "${name%.devel.sql}" == "$name" ] || continue
|
|
[ -z "$updatefile" -o "$updatefile" == "$update" ] || continue
|
|
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
|
|
setx name=basename "$create"
|
|
[ "$dbmode" == devel -o "${name%.devel.sql}" == "$name" ] || continue
|
|
[ -z "$updatefile" -o "$updatefile" == "$update" ] || continue
|
|
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
|
|
setx name=basename "$update"
|
|
[ "$dbmode" == devel -o "${name%.devel.sql}" == "$name" ] || continue
|
|
[ -z "$updatefile" -o "$updatefile" == "$update" ] || continue
|
|
if have_tag admin "$update"; then
|
|
[ -n "$updatedir" ] && name="${update#$updatedir/}" || name="${update#$dbdir/}"
|
|
mysql_admin_update "$name" "$update" "$updatefile"
|
|
else
|
|
name="${update#$dbdir/}"
|
|
mysql_user_update "$name" "$update" "$dbname" "$updatefile"
|
|
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
|
|
|
|
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
|
|
setx name=basename "$drop"
|
|
[ "$dbmode" == devel -o "${name%.devel.sql}" == "$name" ] || continue
|
|
[ -z "$updatefile" -o "$updatefile" == "$update" ] || continue
|
|
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
|
|
setx name=basename "$create"
|
|
[ "$dbmode" == devel -o "${name%.devel.sql}" == "$name" ] || continue
|
|
[ -z "$updatefile" -o "$updatefile" == "$update" ] || continue
|
|
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
|
|
setx name=basename "$update"
|
|
[ "$dbmode" == devel -o "${name%.devel.sql}" == "$name" ] || continue
|
|
[ -z "$updatefile" -o "$updatefile" == "$update" ] || continue
|
|
if have_tag admin "$update"; then
|
|
[ -n "$updatedir" ] && name="${update#$updatedir/}" || name="${update#$dbdir/}"
|
|
oracle_admin_update "$name" "$update" "$updatefile"
|
|
else
|
|
name="${update#$dbdir/}"
|
|
oracle_user_update "$name" "$update" "$dbname" "$updatefile"
|
|
fi
|
|
done
|
|
eend; eclearp
|
|
|
|
############################################################################
|
|
else
|
|
die "BUG: $dbtype: type non implémenté"
|
|
fi
|
|
|
|
eend
|
|
done
|