sqlmig: support de l'importation directe des fichiers csv
This commit is contained in:
parent
d028c47842
commit
d197fc0420
223
sqlmig
223
sqlmig
|
@ -80,13 +80,53 @@ OPTIONS
|
|||
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 '\\N' et --csv-null NULL respectivement
|
||||
|
||||
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
|
||||
|
@ -156,14 +196,9 @@ OPTIONS
|
|||
--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.
|
||||
Ne pas procéder à la conversion des fichiers CSV en SQL
|
||||
--force-data-csv
|
||||
Forcer la conversion des fichiers *-data.csv. Par défaut, la conversion
|
||||
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
|
||||
|
@ -326,12 +361,60 @@ function set_dbdirs() {
|
|||
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
|
||||
|
@ -476,6 +559,13 @@ function mysql__mconf_get() {
|
|||
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" ] && {
|
||||
|
@ -483,14 +573,27 @@ function mysql__mconf_get() {
|
|||
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_csv_null
|
||||
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"
|
||||
|
@ -509,6 +612,10 @@ function mysql_set_userargs() {
|
|||
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=()
|
||||
|
@ -561,7 +668,26 @@ function mysql_user_update() {
|
|||
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
|
||||
|
@ -827,7 +953,7 @@ function oracle_source_adminconf() {
|
|||
}
|
||||
function oracle_source_userconf() {
|
||||
local dir="$1" dbname="$2"
|
||||
unset ORACLE_SID NLS_LANG ADMINCONNECT USERCONNECT SQLMIGLOG SUFFIX CSV_NULL
|
||||
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"
|
||||
|
@ -851,11 +977,11 @@ function oracle_source_userconf() {
|
|||
fi
|
||||
[ -n "$SQLMIGLOG" ] || SQLMIGLOG="/tmp/sqlmig-${ORACLE_SID}-${dbname}.log"
|
||||
[ -z "$suffix" ] && suffix="$SUFFIX"
|
||||
[ -z "$csv_null" ] && {
|
||||
csv_null="$CSV_NULL"
|
||||
[ -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
|
||||
|
@ -918,7 +1044,9 @@ charset=
|
|||
oracle_sid=
|
||||
nls_lang=
|
||||
suffix=
|
||||
csv2sql=
|
||||
csv_null=
|
||||
load_data=
|
||||
profile=
|
||||
type=auto
|
||||
action=update
|
||||
|
@ -946,9 +1074,13 @@ args=(
|
|||
-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
|
||||
|
@ -1060,7 +1192,9 @@ default-character-set=utf8
|
|||
|
||||
[sqlmig]
|
||||
#suffix=
|
||||
csv_null="
|
||||
#csv2sql=0
|
||||
csv_null=
|
||||
#load-data=default"
|
||||
fi
|
||||
|
||||
if [ ! -f "$dbdir/my-${dbname}.cnf" ]; then
|
||||
|
@ -1110,7 +1244,8 @@ USERCONNECT=$dbname/password
|
|||
SQLMIGLOG=\"/tmp/sqlmig-\${ORACLE_SID}-${dbname}.log\"
|
||||
# divers
|
||||
#SUFFIX=
|
||||
#CSV_NULL="
|
||||
#CSV2SQL=0
|
||||
CSV_NULL="
|
||||
fi
|
||||
|
||||
else
|
||||
|
@ -1289,9 +1424,9 @@ function should_update() {
|
|||
elif [ "${name#maint-}" != "$name" ]; then
|
||||
# ignorer les opérations de maintenance par défaut
|
||||
return 1
|
||||
elif [ "$dbmode" != devel -a "${name%.devel.sql}" != "$name" ]; then
|
||||
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.sql
|
||||
# par .devel.*
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
|
@ -1347,13 +1482,17 @@ for dbdir in "${dbdirs[@]}"; do
|
|||
ensure_dbtype "$dbdir" "$type"
|
||||
ensure_dbmode "$dbtype" "$mode"
|
||||
|
||||
if [ -n "$data_csv" ]; then
|
||||
# Conversion csv --> sql
|
||||
array_lsfiles csvs "$dbdir" "*.csv"
|
||||
if [ "$dbtype" == mysql ]; then
|
||||
setx defaults=mysql_get_defaults "$dbdir"
|
||||
set_csv2sql=1
|
||||
set_csv_null=1
|
||||
mysql__mconf_get "$defaults"
|
||||
fix_csv2sql
|
||||
fix_csv_null
|
||||
|
||||
if is_yes "$csv2sql" && [ -n "$data_csv" ]; then
|
||||
# Conversion csv --> sql
|
||||
array_lsfiles csvs "$dbdir" "*.csv"
|
||||
|
||||
etitled "Conversion"
|
||||
for csv in "${csvs[@]}"; do
|
||||
|
@ -1364,19 +1503,14 @@ for dbdir in "${dbdirs[@]}"; do
|
|||
fi
|
||||
|
||||
estep "$csvname --> ${csvname%.csv}.sql"
|
||||
script='{
|
||||
truncate = ($0 ~ /-data_truncate(.devel)?.csv$/)? "1": ""
|
||||
sub(/^.*\//, "")
|
||||
sub(/^[A-Z0-9.]*[0-9]-?/, "")
|
||||
sub(/\.csv$/, "")
|
||||
sub(/\.devel$/, "")
|
||||
sub(/-data(_[a-z]+*)?$/, "")
|
||||
print "truncate=" truncate
|
||||
gsub(/'\''/, "'\'\\\\\'\''")
|
||||
print "table='\''" $0 "'\''"
|
||||
}'
|
||||
eval "$(awk "$script" <<<"$csvname")"
|
||||
"$scriptdir/mysqlloadcsv" >"$sql" ${truncate:+-T} -Z "$csv_null" -nIf "$csv" "$table" --prefix "-- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8"
|
||||
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
|
||||
|
@ -1386,8 +1520,10 @@ for dbdir in "${dbdirs[@]}"; do
|
|||
drops=()
|
||||
creates=()
|
||||
updates=()
|
||||
array_lsfiles files "$dbdir" "*.sql"
|
||||
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
|
||||
|
@ -1395,6 +1531,11 @@ for dbdir in "${dbdirs[@]}"; do
|
|||
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
|
||||
|
||||
############################################################################
|
||||
|
@ -1408,6 +1549,9 @@ for dbdir in "${dbdirs[@]}"; do
|
|||
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
|
||||
|
@ -1449,12 +1593,18 @@ for dbdir in "${dbdirs[@]}"; do
|
|||
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
|
||||
|
||||
|
@ -1511,12 +1661,15 @@ for dbdir in "${dbdirs[@]}"; do
|
|||
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
|
||||
|
||||
|
|
Loading…
Reference in New Issue