add mysql basics

This commit is contained in:
lucaspalomodevelop 2025-04-01 20:54:25 +02:00
parent 1779ac0fd1
commit bb10282749
9 changed files with 273 additions and 74 deletions

BIN
demo_tables/northwind.db Executable file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 114 B

125
main.py
View File

@ -2,14 +2,18 @@ from flask import Flask, render_template, request, send_file
import sqlite3
import os
from graphviz import Digraph
import math
import mysql.connector
from mysql.connector import Error
app = Flask(__name__)
# Verzeichnis für hochgeladene Dateien
UPLOAD_FOLDER = 'uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
UPLOAD_FOLDER = "uploads"
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
def create_er_model(database_file, output_file='er_model.png'):
def create_er_model(database_file, output_file="er_model.png"):
"""Erstellt ein ER-Modell für die angegebene SQLite-Datenbank und speichert es als Bild."""
conn = sqlite3.connect(database_file)
c = conn.cursor()
@ -25,7 +29,7 @@ def create_er_model(database_file, output_file='er_model.png'):
# Für jede Tabelle Informationen über Spalten abrufen und dem Diagramm hinzufügen
for table in tables:
table_name = table[0]
dot.node(table_name, shape='rectangle', color='lightblue2', style='filled')
dot.node(table_name, shape="rectangle", color="lightblue2", style="filled")
# Spalten der Tabelle abrufen
c.execute(f"PRAGMA table_info({table_name});")
@ -34,7 +38,7 @@ def create_er_model(database_file, output_file='er_model.png'):
# Jede Spalte als Knoten im Diagramm hinzufügen
for column in columns:
column_name = column[1]
dot.node(f"{table_name}.{column_name}", label=column_name, shape='ellipse')
dot.node(f"{table_name}.{column_name}", label=column_name, shape="ellipse")
# Verbindung von Tabelle zu Spalte erstellen
dot.edge(table_name, f"{table_name}.{column_name}")
@ -50,45 +54,50 @@ def create_er_model(database_file, output_file='er_model.png'):
parent_column = fk[3]
child_table = table
child_column = fk[4]
dot.edge(f"{parent_table}.{parent_column}", f"{child_table}.{child_column}", label='1..n')
dot.edge(
f"{parent_table}.{parent_column}",
f"{child_table}.{child_column}",
label="1..n",
)
# ER-Modell als Graphviz-Dot-Datei speichern
dot.render(output_file, format='png', cleanup=True)
dot.render(output_file, format="png", cleanup=True)
# Verbindung schließen
conn.close()
return output_file
@app.get("/")
def home():
# HTML-Seite mit den Daten anzeigen
return render_template("index.html")
# Route für den Index
@app.route('/', methods=['GET', 'POST'])
def index():
@app.post("/sqlite")
def sqlite_post():
error = None
er_model = None
table_data = None
if request.method == 'POST':
# Überprüfen, ob eine Datei hochgeladen wurde
if 'file' not in request.files:
error = 'Keine Datei hochgeladen'
if "file" not in request.files:
error = "Keine Datei hochgeladen"
else:
file = request.files['file']
file = request.files["file"]
# Überprüfen, ob eine Datei ausgewählt wurde
if file.filename == '':
error = 'Keine Datei ausgewählt'
if file.filename == "":
error = "Keine Datei ausgewählt"
# Überprüfen, ob die Datei eine SQLite-Datenbank ist
elif file.filename.endswith('.db'):
elif file.filename.endswith(".db"):
# Datei speichern
file_path = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
file_path = os.path.join(app.config["UPLOAD_FOLDER"], file.filename)
file.save(file_path)
# ER-Modell erstellen
er_model_file = create_er_model(file_path)
os.rename("er_model.png.png", "er_model.png")
er_model = er_model_file
# Tabellendaten abrufen
conn = sqlite3.connect(file_path)
cursor = conn.cursor()
@ -100,17 +109,77 @@ def index():
cursor.execute(f"SELECT * FROM {table_name};")
table_data[table_name] = cursor.fetchall()
conn.close()
else:
error = 'Die hochgeladene Datei muss eine SQLite-Datenbankdatei sein'
error = "Die hochgeladene Datei muss eine SQLite-Datenbankdatei sein"
@app.post("/mysql")
def mysql_post():
error = None
er_model = None
table_data = None
# Retrieve MySQL connection details from the request form
host = request.form.get("host")
user = request.form.get("user")
password = request.form.get("password")
if not all([host, user, password]):
error = "Alle Verbindungsdetails und der Dateipfad müssen angegeben werden."
else:
# Überprüfen, ob die MySQL-Datenbank erreichbar ist
try:
conn = mysql.connector.connect(
host=host,
user=user,
password=password,
auth_plugin="mysql_native_password",
)
cursor = conn.cursor()
cursor.execute("SHOW DATABASES;")
databases = cursor.fetchall()
print(databases)
conn.close()
for database in databases:
db_name = database[0]
print(db_name)
conn = mysql.connector.connect(
host=host,
user=user,
password=password,
database=db_name,
auth_plugin="mysql_native_password",
)
cursor = conn.cursor()
cursor.execute("SHOW TABLES;")
tables = cursor.fetchall()
table_data = {}
for table in tables:
table_name = table[0]
cursor.execute(f"SELECT * FROM {table_name};")
table_data[table_name] = cursor.fetchall()
conn.close()
# ER-Modell erstellen
er_model_file = create_er_model(db_name)
os.rename("er_model.png.png", "er_model.png")
er_model = er_model_file
except Error as e:
error = f"Fehler beim Herstellen der Verbindung zur MySQL-Datenbank: {e}"
finally:
if 'conn' in locals() and conn.is_connected():
conn.close()
# HTML-Seite mit den Daten anzeigen
return render_template('index.html', error=error, er_model=er_model, table_data=table_data)
return render_template(
"index.html", error=error, er_model=er_model, table_data=table_data
)
# Route zum Anzeigen des ER-Modells
@app.route('/er_model/<filename>')
@app.route("/er_model/<filename>")
def show_er_model(filename):
return send_file(os.path.abspath(filename), mimetype='image/png')
return send_file(os.path.abspath(filename), mimetype="image/png")
if __name__ == '__main__':
if __name__ == "__main__":
app.run(debug=True)

10
requirements.txt Normal file
View File

@ -0,0 +1,10 @@
blinker==1.9.0
click==8.1.8
Flask==3.1.0
graphviz==0.20.3
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.2
mysql-connector==2.2.9
mysql-connector-python==9.2.0
Werkzeug==3.1.3

44
static/css/tabs.css Executable file
View File

@ -0,0 +1,44 @@
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab.dark-mode table {
border-color: #555555;
}
/* Style the buttons that are used to open the tab content */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
.tabcontent.dark-mode {
background-color: #333333;
color: #ffffff;
}

20
static/js/tabs.js Executable file
View File

@ -0,0 +1,20 @@
function openTab(evt, tabName) {
// Declare all variables
var i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(tabName).style.display = "block";
evt.currentTarget.className += " active";
}

View File

@ -1,23 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{{ url_for('static', filename='../static/css/style.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='../static/css/tabs.css') }}">
<title>SQL Analyzer</title>
</head>
<body>
<header>
<h1>SQLITE Analyzer</h1>
<h1>SQL Analyzer</h1>
</header>
<main>
<div id="dropArea" ondragover="handleDragOver(event)" ondragleave="handleDragLeave(event)" ondrop="handleDrop(event)">
Drag & Drop Datei hierhin oder <input type="file" id="fileInput" style="display: none;" onchange="handleFiles(this.files)"> klicken, um hochzuladen.
<!-- Tab links -->
<div class="tab">
<button class="tablinks" onclick="openTab(event, 'sqlite')">sqlite</button>
<button class="tablinks" onclick="openTab(event, 'mysql')">mysql</button>
</div>
<!-- Tab content -->
<div id="sqlite" class="tabcontent">
<div id="dropArea" ondragover="handleDragOver(event)" ondragleave="handleDragLeave(event)"
ondrop="handleDrop(event)">
Drag & Drop Datei hierhin oder <input type="file" id="fileInput" style="display: none;"
onchange="handleFiles(this.files)"> klicken, um hochzuladen.
</div>
<center><button class="button" id="toggleFormButton" onclick="toggleForm()">DB Hochladen</button></center>
<form id="uploadForm" class="closed" method="post" enctype="multipart/form-data">
<form id="uploadForm" class="closed" method="post" enctype="multipart/form-data" action="/sqlite">
<input type="file" name="file" id="fileInput" onchange="submitForm()">
</form>
@ -55,12 +69,54 @@
<input id="sql_input" type="text" placeholder="SELECT * FROM test;">
<center><button id="execute_button">Ausühren</button></center>
</div>
<div id="mysql" class="tabcontent">
<h2>MySQL</h2>
<p>Hier können Sie MySQL-Datenbankabfragen durchführen.</p>
<form id="mysqlConnectionForm" method="post" action="/mysql">
<input type="text" name="host" placeholder="Host">
<input type="text" name="user" placeholder="Benutzername">
<input type="password" name="password" placeholder="Passwort">
<button type="submit">Verbinden</button>
</form>
<form id="mysqlForm" method="post">
<input type="text" name="query" placeholder="Geben Sie Ihre SQL-Abfrage ein">
<button type="submit">Abfrage ausführen</button>
</form>
{% if mysql_result %}
<h3>Abfrageergebnis</h3>
<table>
<tr>
{% for column_name in mysql_result[0] %}
<th>{{ column_name }}</th>
{% endfor %}
</tr>
{% for row in mysql_result %}
<tr>
{% for value in row %}
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endif %}
</div>
<footer style="background-color: #007bff; color: #ffffff; text-align: center; width: 100%;">
&copy; fingadumbledore 2024 Version 0.1
&copy; lucaspalomodevelop 2025 Version 0.2
</footer>
<button class="dark-mode-button" onclick="toggleDarkMode()">🌙</button>
<script src="/static/js/index.js"></script>
</main>
</body>
</html>
<script src="/static/js/tabs.js" defer> </script>
</body>
</html>

Binary file not shown.

Binary file not shown.