socle_bash/lib/esql.lib

266 lines
14 KiB
Plaintext
Executable File

##----------------------------------------------------------------------------
## Script : esql.lib
## Module Puppet : gnc-script_database_dtsi
## Auteur : Emmanuel Confrere
## Date : 10-02-2016
## Version : 8.0.7-0
## Objet : Cette fonction permet l execution d une requete sur un serveur de base de donnees
##
## Fonction : esql [NomVariable] [Connexion]
##
## Detail : Cette fonction permet l execution d une requete sur un serveur de base de donnees
## La requete est passe a travers la variable d environement ESQL_SQLSTMT.
## Cette fonction s appuis sur les executables psql et sqlplus. Les client de ces
## editeurs doivent donc a minima etre installer.
## La fonction est appelle depuis le shell ou depuis un script de la facon suivante
## esql <VAR> <CNX>
##
## Note : l ordre des parametres n a pas d importance et sont tout deux optionnel.
##
## Le type de base est determine soit par la variable d environement NC_EXPL_DBEDITEUR
## soit par la forme du parametre <CNX>. Ce parametre reconnais le format suivant
## <editeur>:<compte>/<mdp>@<Alias>|@<host:port>//<base>
##
## Ex. cpt/mdp@host:port//base
## cpt/mdp
## cpt/mdp@Alias ( @ est equivalent a //base pour Postgres )
## cpt/mdp//base ( // est equivalent a @Alias pour Oracle)
## /sys ( connexion "/ as sysdba" pour Oracle et "postgres" pour Postgres )
## /sys//base ( pour Postgres se connecte a la base "base" sous le compte "postgres". Ignore par oracle)
##
## Chacune de ces formes peut etre precede par l editeur de la base...
## Ex. oracle:cpt/mdp@Alias
## postgres:/sys
##
## Note : Prefixer par l editeur est necessaire pour interoger une base distante.
## Si l editeur n est pas specifier alors la variable NC_EXPL_DBEDITEUR seras utilisee
## pour determiner l executable a utiliser. La variable NC_EXPL_DBEDITEUR est initialise
## par /opt/expl/conf/shell-env/profile_socle_database.env
##
## Le resultat de la requete est envoye sur la sortie standard ou dans la variable <VAR>
## si cette derniere est renseignee. Si plusieur enragistrement sont
## retourne par la requete la variable <VAR> seras un tableau.
##
## Si aucun parametre de connexion n est fourni (<CNX> est null) alors
## une connxion par defaut sur la base local est utilise
##
## Par defaut la connexion a un serveur Postgres se fait avec le compte postgres
## et si la base n est pas specifier on se connectre a la base postgres.
## Sur un serveur Oracle la connexion se fait par defaut via un compte externe "/"
## sur la base courante defini par la librairie "base".
##
## Si aucune erreur n est releve cette fontion retourne le code de sortie 0.
##
## IMPORTANT : Cette fonction utilise le disque virtuel /dev/shm pour construire les tableaux
##
# ----------------------------------------------------------------------------
# Mise a jour :
# 8.0.7-0 - 10-02-2016 - Emmanuel Confrere - Integration au socle DTSI via Puppet
##----------------------------------------------------------------------------
function esql
{
local VAR_DB=""
local VAR_RES=$1
local VAR_CPT=$2
local VAR_TMP=""
local VAR_CNX=""
local VAR_SES=""
local VAR_LIGNE=""
local VAR_I=1
local PVF=${ESQL_SQLSTMT:${#ESQL_SQLSTMT}-1:1}
local VAR_TMP=""
local VAR_MDP=""
local VAR_CPT2=""
local VAR_ERR=0
local VAR_HOST=""
local VAR_PORT=""
local VAR_BASE=""
fct_message -debug 0 "<lib:esql> ## ---------------------- esql.lib sql submit -------------------- ##"
# -- On controle si l ordre SQL fini bien par ";", le cas echeans on ajoute ce caractere...
[ "${PVF}" = "/" -o "${PVF}" = ";" ] && PVF="" || PVF=";"
# -- On identifie une eventuelle chaine de connexion sur le premier argument
# -- si c est c est le cas, soit il y eu inversion des arguments, soit il n y a pas de nom de variable passe en argument
# -- Si dessous on echange les arguments dans tous les cas ...
if [ `expr match "${VAR_RES}" ".*/.*@.*$"` -ne 0 -o `expr match "${VAR_RES}" ".*/.*$"` -ne 0 -o `expr match "${VAR_RES}" "[a-z,A-Z][a-z,A-Z]*:.*$"` -ne 0 ]
then
VAR_TMP="${VAR_RES}"
VAR_RES="${VAR_CPT}"
VAR_CPT="${VAR_TMP}"
fct_message -debug 0 "<lib:esql> Echange des parametre d entree"
fi
# -- identification de l editeur a partir du format de la chaine de connection
if [ `expr match "${VAR_CPT}" "[a-z]*:"` -ne 0 ]
then
VAR_DB=`echo ${VAR_CPT}|cut -d ":" -f1`
VAR_CPT=`echo ${VAR_CPT}|sed 's/[^:]*:\(.*$\)/\1/'`
else
VAR_DB=${NC_EXPL_DBEDITEUR}
fi
# -- Construction de la chaine de connexion en fontion de l editeur (VAR_CNX) et de la forme du parametre VAR_CPT
case "${VAR_DB}" in
"oracle" ) fct_message -debug 0 "<lib:esql> Connexion a une base Oracle"
if [ -z "${VAR_CPT}" ]
then
VAR_MDP="Aucun"
VAR_CPT2="/"
VAR_CNX="/"
VAR_SES="alter session set current_schema = zzsmai_adm;"
fct_message -debug 2 "<lib:esql> <1> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
fct_message -debug 2 "<lib:esql> <1> Schema courant (VAR_SES) : ${VAR_SES}"
elif [ "${VAR_CPT}" = "/sys" ]
then
VAR_MDP="Aucun"
VAR_CPT2="/ as sysdba"
VAR_CNX="/ as sysdba"
fct_message -debug 2 "<lib:esql> <2> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
elif [ `expr match "${VAR_CPT}" "/sys//.*$"` -ne 0 ]
then
fct_message "<lib:esql> format de connexion non supporte (VAR_CPT=${VAR_CPT})"
return 2
elif [ `expr match "${VAR_CPT}" ".*/.*@.*:[0-9][0-9]*//.*$"` -ne 0 ]
then
VAR_BASE=`echo "${VAR_CPT}"|sed 's#.*/.*@.*:[0-9][0-9]*//\(.*\)$#\1#'`
VAR_HOST=`echo "${VAR_CPT}"|sed 's#.*/.*@\(.*\):[0-9][0-9]*//.*$#\1#'`
VAR_PORT=`echo "${VAR_CPT}"|sed 's#.*/.*@.*:\([0-9][0-9]*\)//.*$#\1#'`
VAR_CPT2=`echo "${VAR_CPT}"|sed 's#\(.*\)/.*@.*:[0-9][0-9]*//.*$#\1#'`
VAR_MDP=`echo "${VAR_CPT}"|sed 's#.*/\(.*\)@.*:[0-9][0-9]*//.*$#\1#'`
VAR_CNX="${VAR_CPT2}/${VAR_MDP}@${VAR_HOST}:${VAR_PORT}/${VAR_BASE}"
fct_message -debug 2 "<lib:esql> <3> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
elif [ `expr match "${VAR_CPT}" ".*/.*@.*$"` -ne 0 ]
then
VAR_HOST=`echo "${VAR_CPT}"|sed 's#.*/.*@\(.*\)$#\1#'`
VAR_CPT2=`echo "${VAR_CPT}"|sed 's#\(.*\)/.*@.*$#\1#'`
VAR_MDP=`echo "${VAR_CPT}"|sed 's#.*/\(.*\)@.*$#\1#'`
VAR_CNX="${VAR_CPT2}/${VAR_MDP}@${VAR_HOST}"
fct_message -debug 2 "<lib:esql> <4> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
elif [ `expr match "${VAR_CPT}" ".*/.*//.*$"` -ne 0 ]
then
VAR_HOST=`echo "${VAR_CPT}"|sed 's#.*/.*//\(.*\)$#\1#'`
VAR_CPT2=`echo "${VAR_CPT}"|sed 's#\(.*\)/.*//.*$#\1#'`
VAR_MDP=`echo "${VAR_CPT}"|sed 's#.*/\(.*\)//.*$#\1#'`
VAR_CNX="${VAR_CPT2}/${VAR_MDP}@${VAR_HOST}"
fct_message -debug 2 "<lib:esql> <5> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
elif [ `expr match "${VAR_CPT}" ".*/.*$"` -ne 0 ]
then
VAR_CPT2=`echo "${VAR_CPT}"|sed 's#\(.*\)/.*$#\1#'`
VAR_MDP=`echo "${VAR_CPT}"|sed 's#.*/\(.*\)$#\1#'`
VAR_CNX="${VAR_CPT2}/${VAR_MDP}"
fct_message -debug 2 "<lib:esql> <6> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
else
fct_message "<lib:esql> Chaine de connexion non reconnu"
return 2
fi ;;
"postgres" ) fct_message -debug 0 "<lib:esql> Connexion a une base Postgres"
if [ -z "${VAR_CPT}" -o "${VAR_CPT}" = "/sys" ]
then
VAR_CPT2="postgres"
VAR_MDP="aucun"
VAR_CNX="postgres://"
fct_message -debug 2 "<lib:esql> <7> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
elif [ `expr match "${VAR_CPT}" "/sys//.*$"` -ne 0 ]
then
VAR_BASE=`echo "${VAR_CPT}"|sed 's#^/sys//\(.*\)$#\1#'`
VAR_CPT2="postgres"
VAR_MDP="aucun"
VAR_CNX="postgres:///${VAR_BASE}"
fct_message -debug 2 "<lib:esql> <8> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
elif [ `expr match "${VAR_CPT}" ".*/.*@.*:[0-9][0-9]*//.*$"` -ne 0 ]
then
VAR_BASE=`echo "${VAR_CPT}"|sed 's#.*/.*@.*:[0-9][0-9]*//\(.*\)$#\1#'`
VAR_HOST=`echo "${VAR_CPT}"|sed 's#.*/.*@\(.*\):[0-9][0-9]*//.*$#\1#'`
VAR_PORT=`echo "${VAR_CPT}"|sed 's#.*/.*@.*:\([0-9][0-9]*\)//.*$#\1#'`
VAR_CPT2=`echo "${VAR_CPT}"|sed 's#\(.*\)/.*@.*:[0-9][0-9]*//.*$#\1#'`
VAR_MDP=`echo "${VAR_CPT}"|sed 's#.*/\(.*\)@.*:[0-9][0-9]*//.*$#\1#'`
VAR_CNX="postgres://${VAR_CPT2}:${VAR_MDP}@${VAR_HOST}:${VAR_PORT}/${VAR_BASE}"
fct_message -debug 2 "<lib:esql> <9> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
elif [ `expr match "${VAR_CPT}" ".*/.*@.*$"` -ne 0 ]
then
VAR_BASE=`echo "${VAR_CPT}"|sed 's#.*/.*@\(.*\)$#\1#'`
VAR_CPT2=`echo "${VAR_CPT}"|sed 's#\(.*\)/.*@.*$#\1#'`
VAR_MDP=`echo "${VAR_CPT}"|sed 's#.*/\(.*\)@.*$#\1#'`
VAR_CNX="postgres://${VAR_CPT2}:${VAR_MDP}@localhost/${VAR_BASE}"
fct_message -debug 2 "<lib:esql> <10> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
elif [ `expr match "${VAR_CPT}" ".*/.*//.*$"` -ne 0 ]
then
VAR_BASE=`echo "${VAR_CPT}"|sed 's#.*/.*//\(.*\)$#\1#'`
VAR_CPT2=`echo "${VAR_CPT}"|sed 's#\(.*\)/.*//.*$#\1#'`
VAR_MDP=`echo "${VAR_CPT}"|sed 's#.*/\(.*\)//.*$#\1#'`
VAR_CNX="postgres://${VAR_CPT2}:${VAR_MDP}@localhost/${VAR_BASE}"
fct_message -debug 2 "<lib:esql> <11> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
elif [ `expr match "${VAR_CPT}" ".*/.*$"` -ne 0 ]
then
VAR_BASE=`echo "${VAR_CPT}"|sed 's#\(.*\)/.*$#\1#'`
VAR_CPT2=${VAR_BASE}
VAR_MDP=`echo "${VAR_CPT}"|sed 's#.*/\(.*\)$#\1#'`
VAR_CNX="postgres://${VAR_CPT2}:${VAR_MDP}@localhost/${VAR_BASE}"
fct_message -debug 2 "<lib:esql> <12> Chaine de connexion (VAR_CNX) : ${VAR_CNX}"
else
fct_message "<lib:esql> Chaine de connexion non reconnu"
return 2
fi ;;
* ) fct_message "<lib:esql> Editeur inconnu : ${VAR_DB}"
return 3 ;;
esac
if [ -n "${ESQL_SQLSTMT}" ]
then
fct_message -debug 0 "<lib:esql> Compte de soumission : ${VAR_CPT2}"
fct_message -debug 3 "<lib:esql> Mot de passe : ${VAR_MDP}"
fct_message -debug 0 "<lib:esql> ${ESQL_SQLSTMT}${PVF}"
case "${VAR_DB}" in
"oracle" ) VAR_TMP=`sqlplus -s ${VAR_CNX} << EndSQL
whenever sqlerror exit 100 rollback;
whenever oserror exit 101 rollback;
set head off pages 0 feed off echo off lines 2048 trim on verify off;
${VAR_SES}
${ESQL_SQLSTMT}${PVF}
EndSQL`
VAR_ERR=$? ;;
"postgres" ) VAR_TMP=`psql -t -q -F "|" -A ${VAR_CNX} << EndSQL
${ESQL_SQLSTMT}${PVF}
EndSQL`
VAR_ERR=$? ;;
esac
if [ ${VAR_ERR} -ne 0 ]
then
export ESQL_NUMROWS=0
[ -n "${SH_SESSION_ID}" ] && fct_message -debug 0 "<lib:esql> ${VAR_TMP}" || echo "${VAR_TMP}"
return 1
else
[ -z "${VAR_TMP}" ] && ESQL_NUMROWS=0 || ESQL_NUMROWS=`echo "${VAR_TMP}"|wc -l`
fct_message -debug 0 "<lib:esql> ESQL_NUMROWS=${ESQL_NUMROWS}"
export ESQL_NUMROWS
fct_message -debug 2 "<lib:esql> ## ---------------------- esql.lib result set -------------------- ##"
if [ -n "${VAR_RES}" ]
then
eval unset ${VAR_RES}
[ ${ESQL_NUMROWS} -eq 0 ] && eval ${VAR_RES}=""
[ ${ESQL_NUMROWS} -eq 1 ] && eval ${VAR_RES}=\"${VAR_TMP}\"
[ ${ESQL_NUMROWS} -eq 1 -a -n "${SH_SESSION_ID}" ] && fct_message -debug 2 "<lib:esql> ${VAR_TMP}"
if [ ${ESQL_NUMROWS} -gt 1 ]
then
VAR_I=0
echo "${VAR_TMP}" > /dev/shm/sql$$.tmp
while read VAR_LIGNE
do
VAR_LIGNE=`echo ${VAR_LIGNE}|sed 's/ */ /g'`
[ -n "${SH_SESSION_ID}" ] && fct_message -debug 2 "<lib:esql> ${VAR_LIGNE}"
eval ${VAR_RES}[${VAR_I}]=\"${VAR_LIGNE}\"
(( VAR_I++ ))
done < /dev/shm/sql$$.tmp
rm -f /dev/shm/sql$$.tmp
fi
else
[ ${ESQL_NUMROWS} -ne 0 ] && echo "${VAR_TMP}"
fi
fct_message -debug 0 "<lib:esql> ## --------------------------------------------------------------- ##"
fi
fi
return 0
}
typeset -Ffx esql