ajouter les options -L, -I, -U à mysqlloadcsv

maj de la doc
This commit is contained in:
Jephté Clain 2014-03-03 17:08:49 +04:00
parent 42779acb55
commit 9d88d7a72f
2 changed files with 149 additions and 51 deletions

View File

@ -15,13 +15,13 @@ db est le nom de la base de données. Cette argument n'est lu que si le nom
ni spécifié avec l'option -D ni spécifié avec l'option -D
OPTIONS OPTIONS
-h HOST -h, --host HOST
-P PORT -P, --port PORT
-u USER -u, --user USER
-pPASSWORD -pPASSWORD
-D DATABASE -D, --database DATABASE
Informations de connexion à la base de données Informations de connexion à la base de données
-C CONFIG -C, --config CONFIG
Prendre les informations de connexion depuis le fichier spécifié. Prendre les informations de connexion depuis le fichier spécifié.
Le fichier doit être de la forme Le fichier doit être de la forme
host=HOST host=HOST
@ -41,11 +41,11 @@ OPTIONS
sourcer les fichiers de configuration. Cela permet d'avoir des fichiers sourcer les fichiers de configuration. Cela permet d'avoir des fichiers
de configuration qui calculent dynamiquement les paramètres en fonction de configuration qui calculent dynamiquement les paramètres en fonction
de la valeur du profil. de la valeur du profil.
-N -N, --no-headers
Ne pas afficher les en-têtes Ne pas afficher les en-têtes
-c -c, --force
Continuer le traitement même en cas d'erreur Continuer le traitement même en cas d'erreur
-r -r, --raw
Ne pas autoriser mysql à mettre en échappement certaines valeurs Ne pas autoriser mysql à mettre en échappement certaines valeurs
retournées par le serveur. Par défaut, les transformations suivantes retournées par le serveur. Par défaut, les transformations suivantes
sont effectuées: sont effectuées:
@ -53,9 +53,9 @@ OPTIONS
tab --> \\t tab --> \\t
nul --> \\0 nul --> \\0
\\ --> \\\\ \\ --> \\\\
-n -n, --nulls
Transformer dans le flux en sortie les valeurs NULL en chaines vides Transformer dans le flux en sortie les valeurs NULL en chaines vides
-f INPUT -f, --input INPUT
Lire la requête depuis le fichier input au lieu de le lire depuis la Lire la requête depuis le fichier input au lieu de le lire depuis la
ligne de commande ou l'entrée standard. Ne pas spécifier cette option ligne de commande ou l'entrée standard. Ne pas spécifier cette option
ou utiliser '-' pour lire depuis l'entrée standard. ou utiliser '-' pour lire depuis l'entrée standard.

View File

@ -26,12 +26,12 @@ sont effectuées par MySQL:
\\N --> NULL \\N --> NULL
OPTIONS OPTIONS
-h host -h, --host host
-P port -P, --port port
-u user -u, --user user
-ppassword -ppassword
Informations de connexion à la base de données Informations de connexion à la base de données
-C CONFIG -C, --config CONFIG
Prendre les informations de connexion depuis le fichier spécifié. Prendre les informations de connexion depuis le fichier spécifié.
Le fichier doit être de la forme Le fichier doit être de la forme
host=HOST.TLD host=HOST.TLD
@ -54,25 +54,54 @@ OPTIONS
sourcer les fichiers de configuration. Cela permet d'avoir des fichiers sourcer les fichiers de configuration. Cela permet d'avoir des fichiers
de configuration qui calculent dynamiquement les paramètres en fonction de configuration qui calculent dynamiquement les paramètres en fonction
de la valeur du profil. de la valeur du profil.
-f INPUT -f, --input INPUT
Fichier en entrée. Ne pas spécifier cette option ou utiliser '-' pour Fichier en entrée. Ne pas spécifier cette option ou utiliser '-' pour
lire depuis l'entrée standard. lire depuis l'entrée standard.
-s NBLINES -s, --skip-lines NBLINES
Nombre de lignes à sauter dans le fichier en entrée Nombre de lignes à sauter dans le fichier en entrée
-n, --fake
Ne pas effectuer l'opération. Afficher simplement la commande SQL.
-T, --truncate -T, --truncate
Vider la table avant d'effectuer le chargement Vider la table avant d'effectuer le chargement
-k, --update-key KEY -L, --load-data
Charger les données avec la commande 'load data local'. C'est l'option
par défaut.
-I, --insert-data
Charger les données en générant des commandes 'insert into'. L'effet est
en principe le même avec l'option -L (sauf que certains formats de date
exotiques seront correctement importés). Cette option peut aussi être
utilisée avec l'option -n pour générer une liste de commande à corriger
et/ou adapter.
-U, -k, --update-data KEY
Au lieu de charger de nouvelles données, essayer de mettre à jour la Au lieu de charger de nouvelles données, essayer de mettre à jour la
table avec les données du fichier CSV. KEY est le nom de la colonne qui table. KEY est le nom de la colonne qui est utilisée comme clé. Toutes
est utilisée comme clé. Toutes les autres colonnes sont les nouvelles les autres colonnes sont les nouvelles données à mettre à jour. Si
données à mettre à jour. aucune ligne ne correspond à une clé donnée, la mise à jour pour cette
-n, --fake ligne est ignorée.
Ne pas effectuer l'opération. Afficher simplement la commande SQL." Note: utiliser les options -T et -U ensemble n'a pas de sens, mais -T
est quand même honoré."
} }
source "$(dirname "$0")/ulib/ulib" && source "$(dirname "$0")/ulib/ulib" || exit 1; urequire DEFAULTS awk
urequire DEFAULTS awk ||
exit 1 __AWK_MYSQLFUNCS='
function format_sqlvalue(value) {
if (value ~ /^[0-9]+$/) {
} else if (value ~ /^[0-9][0-9]\/[0-9][0-9]\/[0-9][0-9]$/) {
value = "str_to_date('\''" value "'\'', '\''%d/%m/%y'\'')"
} else if (value ~ /^[0-9][0-9]\/[0-9][0-9]\/[0-9][0-9][0-9][0-9]$/) {
value = "str_to_date('\''" value "'\'', '\''%d/%m/%Y'\'')"
} else if (value ~ /^[0-9][0-9][0-9][0-9]\/[0-9][0-9]\/[0-9][0-9]$/) {
value = "str_to_date('\''" value "'\'', '\''%Y/%m/%d'\'')"
} else if (value ~ /^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/) {
value = "str_to_date('\''" value "'\'', '\''%Y-%m-%d'\'')"
} else {
gsub(/'\''/, "'\'\''", value)
value = "'\''" value "'\''"
}
return value
}
'
host= host=
port= port=
@ -83,8 +112,9 @@ profile=
input= input=
skip_lines= skip_lines=
truncate= truncate=
update_key=
fake= fake=
method=load
update_key=
parse_opts "${PRETTYOPTS[@]}" \ parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with display_help' \ --help '$exit_with display_help' \
-h:,-H:,--host: host= \ -h:,-H:,--host: host= \
@ -94,17 +124,13 @@ parse_opts "${PRETTYOPTS[@]}" \
-C:,--config: configs \ -C:,--config: configs \
-f:,--input: input= \ -f:,--input: input= \
-s:,--skip-lines: skip_lines= \ -s:,--skip-lines: skip_lines= \
-T,--truncate truncate=1 \
-k:,--update-key: update_key= \
-n,--fake fake=1 \ -n,--fake fake=1 \
-T,--truncate truncate=1 \
-L,--load-data method=load \
-I,--insert-data method=insert \
-U:,-k:,--update-data: '$method=update; set@ update_key' \
@ args -- "$@" && set -- "${args[@]}" || die "$args" @ args -- "$@" && set -- "${args[@]}" || die "$args"
if [ -n "$update_key" ]; then
# update_key n'est pas encore implémenté
ewarn "L'option -k n'est pas encore implémentée. Activation de --fake pour éviter de perdre des données"
fake=1
fi
dbtable="$1"; shift dbtable="$1"; shift
fields=() fields=()
while [ "$#" -gt 0 -a "$1" != "--" ]; do while [ "$#" -gt 0 -a "$1" != "--" ]; do
@ -154,30 +180,102 @@ else
fi fi
array_split fields "$(awkcsv -s "$skip_lines" -e '{ print array_join(HEADERS, ","); exit }' <"$input")" "," array_split fields "$(awkcsv -s "$skip_lines" -e '{ print array_join(HEADERS, ","); exit }' <"$input")" ","
cfields="$(array_join fields ,)" cfields="$(array_join fields ,)"
skip_lines=$(($skip_lines + 1))
fi fi
[ -n "$truncate" ] && truncate="truncate table \`$table\`;"
loadcsv="load data local infile '$input' into table \`$table\` character set 'utf8' fields terminated by ',' optionally enclosed by '\\\"' escaped by '\\\\' lines terminated by '\\n' starting by '' ignore $skip_lines lines ($cfields);"
mysqlargs=( mysqlargs=(
${host:+-h "$host"} ${port:+-P "$port"} ${host:+-h "$host"} ${port:+-P "$port"}
${user:+-u "$user"} ${database:+-D "$database"} ${user:+-u "$user"} ${database:+-D "$database"}
) )
[ "$password" != "--NOT-SET--" ] && mysqlargs=("${mysqlargs[@]}" -p"$password") [ "$password" != "--NOT-SET--" ] && mysqlargs=("${mysqlargs[@]}" -p"$password")
mysqlargs=("${mysqlargs[@]}"
"$truncate$loadcsv"
--
--local-infile=1
)
cmd=("$scriptdir/mysqlcsv" "${mysqlargs[@]}" "$@") [ -n "$truncate" ] && truncate="truncate table \`$table\`;"
if [ -n "$fake" ]; then
echo "-- Requêtes SQL:" if [ "$method" == load ]; then
[ -n "$truncate" ] && echo "$truncate" skip_lines=$(($skip_lines + 1))
echo "$loadcsv" loadcsv="load data local infile '$input' into table \`$table\` character set 'utf8' fields terminated by ',' optionally enclosed by '\\\"' escaped by '\\\\' lines terminated by '\\n' starting by '' ignore $skip_lines lines ($cfields);"
echo "-- Commande à lancer en ligne de commande pour importer la table dans MySQL:" mysqlargs=("${mysqlargs[@]}"
echo "-- $(quoted_args "${cmd[@]}")" "$truncate$loadcsv"
--
--local-infile=1
)
cmd=("$scriptdir/mysqlcsv" "${mysqlargs[@]}" "$@")
r=0
if [ -n "$fake" ]; then
echo "-- Requêtes SQL:"
[ -n "$truncate" ] && echo "$truncate"
echo "$loadcsv"
echo "-- Commande à lancer pour importer la table dans MySQL:"
echo "-- $(quoted_args "${cmd[@]}")"
else
"${cmd[@]}"; r=$?
fi
exit $r
elif [ "$method" == insert ]; then
ac_set_tmpfile inserts
[ -n "$truncate" ] && echo "$truncate" >>"$inserts"
awkcsv <"$input" >>"$inserts" -s "$skip_lines" -v table="$table" \
-a "$__AWK_MYSQLFUNCS"'{
fields = array_join(ORIGHEADERS, ", ")
count = length(ORIGHEADERS)
values = ""
for (i = 1; i <= count; i++) {
if (i > 1) values = values ", "
values = values format_sqlvalue($i)
}
print "insert into `" table "` (" fields ") values (" values ");"
}
END {
print "commit;"
}'
r=0
if [ -n "$fake" ]; then
cat "$inserts"
else
cat "$inserts" | "$scriptdir/mysqlcsv" "${mysqlargs[@]}" -f -; r=$?
fi
ac_clean "$inserts"
exit $r
elif [ "$method" == update ]; then
array_contains fields "$update_key" || die "$update_key: ce champ n'existe pas dans la source"
ac_set_tmpfile updates
[ -n "$truncate" ] && echo "$truncate" >>"$updates"
awkcsv <"$input" >>"$updates" -s "$skip_lines" \
-v table="$table" -v update_key="$update_key" \
-a "$__AWK_MYSQLFUNCS"'{
set_values = ""
cond = ""
count = length(ORIGHEADERS)
for (i = 1; i <= count; i++) {
field = ORIGHEADERS[i]
value = format_sqlvalue($i)
if (field == update_key) {
cond = field "=" value
} else {
if (set_values) set_values = set_values ", "
set_values = set_values field "=" value
}
}
print "update `" table "` set " set_values " where " cond ";"
}
END {
print "commit;"
}'
r=0
if [ -n "$fake" ]; then
cat "$updates"
else
cat "$updates" | "$scriptdir/mysqlcsv" "${mysqlargs[@]}" -f -; r=$?
fi
ac_clean "$updates"
exit $r
else else
exec "${cmd[@]}" die "BUG: $method: method non implémentée"
fi fi