[PYTHON] Je souhaite gérer la version d'une définition de table DB dans un environnement hérité tel que "J'ajoute un schéma DB que je ne comprends pas sans le savoir ..."

Ce que je voulais faire

--Je souhaite gérer la version de la définition de la table DB --Je veux revoir le correctif

(Je pense qu'il y a peu de nouveaux services pour le moment) Je pense que ce serait pratique si le service est tel que chaque développeur modifie la définition uniquement parce que le maître de la définition de la table est dans la base de données (il est difficile pour les autres développeurs de le reconnaître).

Code d'exportation

Ceci est censé être exécuté uniquement pour la première fois Les modifications ultérieures de la définition de la table prennent la forme d'une modification du fichier de sortie.

"""export_database_schema.py
Utilisé pour exporter l'instruction CREATE TABLE depuis la base de données
    optional arguments:
        -h, --help            show this help message and exit
        --user USER Nom d'utilisateur de la base de données
        --mot de passe mot de passe de la base de données mot de passe
        --host HOST nom d'hôte de la base de données
        --port Numéro de port de la base de données PORT
        --charset Code de caractère de la base de données CHARSET
        --target TARGET [TARGET ...]
Liste de bases de données à exporter(Espace séparé)
"""

import os
import sys
import shutil
import pymysql
import argparse

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

#Réglage de l'argument
parser = argparse.ArgumentParser()
parser.add_argument("--user", help="Nom d'utilisateur de la base de données", default="root")
parser.add_argument("--password", help="Mot de passe de la base de données", default="password")
parser.add_argument("--host", help="Nom d'hôte de la base de données", default="127.0.0.1")
parser.add_argument("--port", help="Numéro de port de la base de données", default=3306)
parser.add_argument("--charset", help="Code de caractère de la base de données", default="utf8mb4")
parser.add_argument("--target", help="Liste de bases de données à exporter(Espace séparé)",
                    default=["users", "shops"],
                    nargs="+")
args = parser.parse_args()

print("Connection: mysql://%s:%s@%s:%s?charset=%s" % (
    args.user,
    args.password,
    args.host,
    args.port,
    args.charset))
con = pymysql.connect(
    user=args.user,
    password=args.password,
    host=args.host,
    port=args.port,
    charset=args.charset)

with con.cursor() as cursor:
    sql = "SHOW DATABASES"
    cursor.execute(sql)
    databases = cursor.fetchall()
    #Le traitement d'exportation est effectué uniquement lorsque le DB spécifié existe.
    for d in databases:
        if d[0] not in args.target:
            continue
        #Créer un répertoire pour chaque DB(Supprimer une fois s'il existe)
        currentDirName = "%s/%s" % (ROOT_DIR, d[0])
        if os.path.isdir(currentDirName):
            shutil.rmtree(currentDirName)
        os.mkdir(currentDirName)
        dirname = "%s/schemas" % (currentDirName)
        os.mkdir(dirname)

        print("Export database: ", d[0])
        sql = "USE %s" % d[0]
        cursor.execute(sql)
        sql = "SHOW TABLES"
        cursor.execute(sql)
        tables = cursor.fetchall()
        for t in tables:
            print("\tExporting ", t[0])
            sql = "SHOW CREATE TABLE %s" % t
            cursor.execute(sql)
            schema = cursor.fetchone()
            filename = "%s/%s.sql" % (dirname, t[0])
            with open(filename, mode="w") as f:
                f.write(schema[1] + ";\n\n")

con.close()

Par exemple, python export_database_schema.py --cible utilisateurs boutiques Le fichier d'instruction CREATE sera configuré avec la structure de répertoires suivante lors de l'exécution.

├── users
│   └── schemas #Stocke l'instruction CREATE pour les tables dans la base de données des utilisateurs
└── shops
    └── schemas #Stocke l'instruction CREATE pour les tables dans les boutiques DB

Importer le code

#!/bin/bash

usage() {
  cat << EOS
Usage: $0 [option]
	-t Répertoire de définition de la table cible TARGET
	-d Nom de la base de données de destination d'importation DATABASE
	-Nom d'hôte de la base de données HOST
	-u Nom d'utilisateur de la base de données USER
	-p Mot de passe de la base de données PASSWORD
	-Numéro de port de la base de données P PORT
	-y Omettre l'invite de confirmation d'exécution
EOS
  exit 1
}

TARGET=""
DATABASE_NAME=""
HOST="127.0.0.1"
USER="root"
PASSWORD=""
PORT="3306"
AUTO_YES=false


while getopts d:t:H:u:p:P:yh OPT
do
  case $OPT in
    d) DATABASE_NAME=$OPTARG ;;
    t) TARGET=$OPTARG ;;
    H) HOST=$OPTARG ;;
    u) USER=$OPTARG ;;
    p) PASSWORD=$OPTARG ;;
    P) PORT=$OPTARG ;;
    y) AUTO_YES=true ;;
    h) usage ;;
  esac
done

ROOT_PATH=$(dirname "$(cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd)")

if [ "${DATABASE_NAME}" == "" ]; then
  echo "Veuillez spécifier la base de données à importer."
  echo "  ./$0 -d DATABASE_NAME"
  exit 1
fi

if [ ! -d $ROOT_PATH/$TARGET/schemas ]; then
  echo "Le répertoire de définition de table spécifié n'existe pas"
  echo "${ROOT_PATH}Vérifiez si le répertoire existe sous"
  echo "  ./$0 -t TARGET"
  exit 1
fi

echo "Paramètres-------------------------"
echo "TARGET:		$TARGET"
echo "DATABASE_NAME:	$DATABASE_NAME"
echo "HOST:		$HOST"
echo "USER:		$USER"
echo "PASSWORD:		$PASSWORD"
echo "PORT:		$PORT"
echo "------------------------------------"

#Vérification
if ! "${AUTO_YES}"; then
  read -p "\"$DATABASE_NAME\"Puis-je initialiser la base de données?(y/N)" yn
  case "$yn" in
    [yY]*) ;;
    *) exit 1;;
  esac
fi

echo "Initialisation de la base de données en cours..."
CMD="mysql -h$HOST"
if [ "$USER" != "" ]; then
  CMD="$CMD -u$USER"
fi
if [ "$PASSWORD" != "" ]; then
  CMD="$CMD -p$PASSWORD"
fi
if [ "$PORT" != "" ]; then
  CMD="$CMD -P$PORT"
fi

echo 'SET FOREIGN_KEY_CHECKS = 0;' > "${ROOT_PATH}/tmp.sql"
cat $ROOT_PATH/$TARGET/schemas/*.sql >> "${ROOT_PATH}/tmp.sql"

`$CMD -e "set FOREIGN_KEY_CHECKS=0; DROP DATABASE IF EXISTS $DATABASE_NAME;"`
`$CMD -e "CREATE DATABASE $DATABASE_NAME;"`
`$CMD -t $DATABASE_NAME < "${ROOT_PATH}/tmp.sql"`

rm "${ROOT_PATH}/tmp.sql"
echo "Terminé"

#Si vous souhaitez mettre les données initiales pour le test, placez le fichier au format suivant et importez-le ensemble
# echo "Création des données initiales..."
# `$CMD -t $DATABASE_NAME < "${ROOT_PATH}/${TARGET}/testdata/dump.sql"`
# echo "Terminé"

exit 0

L'importation est Par exemple, ./scripts/import_database_schema.sh -t utilisateurs -d utilisateurs -y Je vais le faire sous la forme de.

En fonctionnement réel, les données de test sont configurées comme indiqué ci-dessous, et les données de test sont également importées au moment de l'importation, et le test est exécuté avec des actions github.

├── users
│   ├── testdata #Stocke les données de test des utilisateurs DB
│   └── schemas  #Stocke l'instruction CREATE pour les tables dans la base de données des utilisateurs
└── shops
    ├── testdata #Stocke les données de test des magasins DB
    └── schemas  #Stocke l'instruction CREATE pour les tables dans les boutiques DB

Recommended Posts

Je souhaite gérer la version d'une définition de table DB dans un environnement hérité tel que "J'ajoute un schéma DB que je ne comprends pas sans le savoir ..."
Je souhaite convertir une table convertie en PDF en Python en CSV
Je veux créer un environnement Python
Je veux créer un bel environnement de développement Python pour mon nouveau Mac
Je souhaite créer une file d'attente prioritaire pouvant être mise à jour avec Python (2.7)
Je souhaite définir un cycle de vie dans la définition de tâche d'ECS
Le programme Python est lent! Je veux accélérer! Dans ce cas ...